From c68f859592288ded724acfa879b5a3c62c6b9902 Mon Sep 17 00:00:00 2001 From: TrevorFlanigan Date: Sat, 5 Feb 2022 14:45:54 -0800 Subject: [PATCH 1/4] added basic layout --- frontend/android/app/build.gradle | 2 +- frontend/lib/styles/font_styles.dart | 15 ++++--- frontend/lib/widgets/interactive_task.dart | 26 ++++++++---- frontend/lib/widgets/task_details.dart | 47 +++++++++++++++++++++ frontend/lib/widgets/touchable_opacity.dart | 40 ++++++++++++++++++ 5 files changed, 114 insertions(+), 16 deletions(-) create mode 100644 frontend/lib/widgets/task_details.dart create mode 100644 frontend/lib/widgets/touchable_opacity.dart diff --git a/frontend/android/app/build.gradle b/frontend/android/app/build.gradle index 4272a7e..ab9dea3 100644 --- a/frontend/android/app/build.gradle +++ b/frontend/android/app/build.gradle @@ -27,7 +27,7 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { compileSdkVersion 30 - + minSdkVersion 19 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 diff --git a/frontend/lib/styles/font_styles.dart b/frontend/lib/styles/font_styles.dart index 2d67591..354dd72 100644 --- a/frontend/lib/styles/font_styles.dart +++ b/frontend/lib/styles/font_styles.dart @@ -5,21 +5,24 @@ TextStyle mainStyle = const TextStyle( color: Colors.black, fontSize: 14, height: 0.5, - fontWeight: FontWeight.w400 -); + fontWeight: FontWeight.w400); TextStyle linkStyle = const TextStyle( fontFamily: 'SF Pro', color: Color.fromRGBO(29, 56, 80, 1.0), fontSize: 14, height: 0.5, - fontWeight: FontWeight.w400 -); + fontWeight: FontWeight.w400); TextStyle boldStyle = const TextStyle( fontFamily: 'SF Pro', color: Colors.black, fontSize: 14, height: 0.5, - fontWeight: FontWeight.w800 -); \ No newline at end of file + fontWeight: FontWeight.w800); + +TextStyle titleStyle = const TextStyle( + fontFamily: 'SF Pro', + color: Colors.black, + fontSize: 24, + fontWeight: FontWeight.w400); diff --git a/frontend/lib/widgets/interactive_task.dart b/frontend/lib/widgets/interactive_task.dart index 38e8fcf..2f81eed 100644 --- a/frontend/lib/widgets/interactive_task.dart +++ b/frontend/lib/widgets/interactive_task.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:lp_task_scheduler/widgets/task_details.dart'; +import 'package:lp_task_scheduler/widgets/touchable_opacity.dart'; import '../src/task.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; @@ -42,15 +44,21 @@ class InteractiveTask extends StatelessWidget { @override Widget build(BuildContext context) { dynamic data = ds!.data(); - return Dismissible( - onDismissed: (direction) => dismissItem(direction), - key: UniqueKey(), - child: Task( - title: data["title"].toString(), - description: data["description"].toString(), - ds: ds), - background: buildSwipeActionLeft(), - secondaryBackground: buildSwipeActionRight(), + return TouchableOpacity( + onTap: () { + Navigator.push( + context, MaterialPageRoute(builder: (context) => TaskDetails())); + }, + child: Dismissible( + onDismissed: (direction) => dismissItem(direction), + key: UniqueKey(), + child: Task( + title: data["title"].toString(), + description: data["description"].toString(), + ds: ds), + background: buildSwipeActionLeft(), + secondaryBackground: buildSwipeActionRight(), + ), ); } diff --git a/frontend/lib/widgets/task_details.dart b/frontend/lib/widgets/task_details.dart new file mode 100644 index 0000000..7e991f4 --- /dev/null +++ b/frontend/lib/widgets/task_details.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:lp_task_scheduler/styles/font_styles.dart'; + +class TaskDetails extends StatefulWidget { + TaskDetails({Key? key}) : super(key: key); + + @override + State createState() => _TaskDetailsState(); +} + +class _TaskDetailsState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Task Details'), + ), + body: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text("Title", style: titleStyle), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Text("Assignee"), + Text("Due Date"), + ], + ), + Center( + child: Text("Points"), + ), + Center( + child: Text("Description"), + ), + ElevatedButton( + onPressed: () { + print("hello"); + }, + child: Text("Mark as Completed")) + ], + )), + ); + } +} diff --git a/frontend/lib/widgets/touchable_opacity.dart b/frontend/lib/widgets/touchable_opacity.dart new file mode 100644 index 0000000..dd035e9 --- /dev/null +++ b/frontend/lib/widgets/touchable_opacity.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; + +typedef void VoidFunction(); + +class TouchableOpacity extends StatefulWidget { + final Widget child; + final VoidFunction onTap; + final Duration duration = const Duration(milliseconds: 50); + final double opacity = 0.5; + + TouchableOpacity({required this.child, required this.onTap}); + + @override + _TouchableOpacityState createState() => _TouchableOpacityState(); +} + +class _TouchableOpacityState extends State { + bool isDown = false; + + @override + void initState() { + super.initState(); + setState(() => isDown = false); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTapDown: (_) => setState(() => isDown = true), + onTapUp: (_) => setState(() => isDown = false), + onTapCancel: () => setState(() => isDown = false), + onTap: widget.onTap, + child: AnimatedOpacity( + child: widget.child, + duration: widget.duration, + opacity: isDown ? widget.opacity : 1, + ), + ); + } +} From 09b61623722a276e3b42dcba2dd36baa72826ee3 Mon Sep 17 00:00:00 2001 From: TrevorFlanigan Date: Fri, 11 Feb 2022 11:52:01 -0800 Subject: [PATCH 2/4] functional with no styling --- frontend/lib/widgets/date_panel.dart | 22 +++++---- frontend/lib/widgets/interactive_task.dart | 6 ++- frontend/lib/widgets/new_task_panel.dart | 8 +++- frontend/lib/widgets/task_details.dart | 52 ++++++++++++++++++---- 4 files changed, 69 insertions(+), 19 deletions(-) diff --git a/frontend/lib/widgets/date_panel.dart b/frontend/lib/widgets/date_panel.dart index 384ae24..58dc8af 100644 --- a/frontend/lib/widgets/date_panel.dart +++ b/frontend/lib/widgets/date_panel.dart @@ -3,13 +3,11 @@ import 'package:lp_task_scheduler/widgets/new_task_panel.dart'; import 'package:syncfusion_flutter_datepicker/datepicker.dart'; class DatePanel extends StatefulWidget { - Function setViewState = (ViewState state) => {}; - Function setSelectedDate = (DateTime date) => {}; - DatePanel(Function _setViewState, Function _setSelectedDate, Key? key) - : super(key: key) { - setSelectedDate = _setSelectedDate; - setViewState = _setViewState; - } + Function onPressed; + Function onSelectionChanged; + DateTime? initialDate; + DatePanel(this.onPressed, this.onSelectionChanged, this.initialDate, Key? key) + : super(key: key) {} @override State createState() => _DatePanelState(); @@ -17,6 +15,11 @@ class DatePanel extends StatefulWidget { class _DatePanelState extends State { @override + @override + void initState() { + super.initState(); + } + Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -24,9 +27,10 @@ class _DatePanelState extends State { Container( margin: const EdgeInsets.all(30), child: SfDateRangePicker( + initialDisplayDate: widget.initialDate, onSelectionChanged: (DateRangePickerSelectionChangedArgs args) { print("hello"); - widget.setSelectedDate(args.value); + widget.onSelectionChanged(args.value); }, selectionMode: DateRangePickerSelectionMode.single, initialSelectedDate: DateTime.now(), @@ -55,7 +59,7 @@ class _DatePanelState extends State { color: Colors.black, fontWeight: FontWeight.bold), ), onPressed: () { - widget.setViewState(ViewState.standard); + widget.onPressed(); }, ), )) diff --git a/frontend/lib/widgets/interactive_task.dart b/frontend/lib/widgets/interactive_task.dart index 2f81eed..8f4bdd3 100644 --- a/frontend/lib/widgets/interactive_task.dart +++ b/frontend/lib/widgets/interactive_task.dart @@ -47,7 +47,11 @@ class InteractiveTask extends StatelessWidget { return TouchableOpacity( onTap: () { Navigator.push( - context, MaterialPageRoute(builder: (context) => TaskDetails())); + context, + MaterialPageRoute( + builder: (context) => TaskDetails( + ds: ds, + ))); }, child: Dismissible( onDismissed: (direction) => dismissItem(direction), diff --git a/frontend/lib/widgets/new_task_panel.dart b/frontend/lib/widgets/new_task_panel.dart index 945ae16..4337490 100644 --- a/frontend/lib/widgets/new_task_panel.dart +++ b/frontend/lib/widgets/new_task_panel.dart @@ -76,6 +76,12 @@ class _TaskPanel extends State { }); } + void onDatePressed() { + setState(() { + _showState = ViewState.standard; + }); + } + void setSelectedDate(DateTime date) { setState(() { selectedDate = date; @@ -98,7 +104,7 @@ class _TaskPanel extends State { Widget renderFromViewState() { switch (_showState) { case ViewState.date: - return DatePanel(setViewState, setSelectedDate, null); + return DatePanel(onDatePressed, setSelectedDate, null, null); case ViewState.standard: default: return Column( diff --git a/frontend/lib/widgets/task_details.dart b/frontend/lib/widgets/task_details.dart index 7e991f4..369b750 100644 --- a/frontend/lib/widgets/task_details.dart +++ b/frontend/lib/widgets/task_details.dart @@ -1,16 +1,40 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; import 'package:lp_task_scheduler/styles/font_styles.dart'; +import 'package:lp_task_scheduler/widgets/new_task_panel.dart'; -class TaskDetails extends StatefulWidget { - TaskDetails({Key? key}) : super(key: key); +import 'assign_dropdown.dart'; +import 'date_panel.dart'; +class TaskDetails extends StatefulWidget { + final DocumentSnapshot? ds; + TaskDetails({this.ds, Key? key}) : super(key: key); @override State createState() => _TaskDetailsState(); } class _TaskDetailsState extends State { + ViewState _viewState = ViewState.standard; + + void setViewState(ViewState state) { + setState(() { + _viewState = state; + }); + } + + void completeTask() { + widget.ds!.reference.update({"status": "complete"}); + } + @override Widget build(BuildContext context) { + if (widget.ds == null || !widget.ds!.exists) { + return Container(); + } + dynamic data = widget.ds!.data(); + DateTime date = DateTime.parse(data["dueDate"].toDate().toString()); + print(data); return Scaffold( appBar: AppBar( title: Text('Task Details'), @@ -20,24 +44,36 @@ class _TaskDetailsState extends State { children: [ Padding( padding: const EdgeInsets.all(8.0), - child: Text("Title", style: titleStyle), + child: Text(data["title"], style: titleStyle), ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - Text("Assignee"), - Text("Due Date"), + AssignDropdown( + "ch3p51@gmail.com", (String n) {}, "Unassigned", null), + TextButton.icon( + icon: const Icon(Icons.calendar_today), + label: Text('Due ${DateFormat('MMM dd yyyy').format(date)}'), + onPressed: () { + setViewState(ViewState.date); + }, + ), ], ), Center( - child: Text("Points"), + child: Text(data["points"] != null + ? "Points: ${data["points"]}" + : "Points: ${1}"), ), Center( - child: Text("Description"), + child: Text(data["description"] != null + ? "Description: ${data["description"]}" + : "Description: ${'Add a description'}"), ), ElevatedButton( onPressed: () { - print("hello"); + completeTask(); + print("completedTask"); }, child: Text("Mark as Completed")) ], From bafe0930cd8f04e4f78bc6de606b280b64058df1 Mon Sep 17 00:00:00 2001 From: TrevorFlanigan Date: Tue, 8 Mar 2022 01:00:14 -0800 Subject: [PATCH 3/4] finished styling task detail --- frontend/lib/styles/font_styles.dart | 15 +++ .../widgets/details/detail_description.dart | 35 +++++++ frontend/lib/widgets/details/detail_row.dart | 51 +++++++++++ .../lib/widgets/details/finish_button.dart | 45 +++++++++ .../lib/widgets/details/task_details.dart | 91 +++++++++++++++++++ frontend/lib/widgets/details/task_owner.dart | 63 +++++++++++++ frontend/lib/widgets/interactive_task.dart | 2 +- frontend/lib/widgets/task_details.dart | 83 ----------------- 8 files changed, 301 insertions(+), 84 deletions(-) create mode 100644 frontend/lib/widgets/details/detail_description.dart create mode 100644 frontend/lib/widgets/details/detail_row.dart create mode 100644 frontend/lib/widgets/details/finish_button.dart create mode 100644 frontend/lib/widgets/details/task_details.dart create mode 100644 frontend/lib/widgets/details/task_owner.dart delete mode 100644 frontend/lib/widgets/task_details.dart diff --git a/frontend/lib/styles/font_styles.dart b/frontend/lib/styles/font_styles.dart index 354dd72..484a060 100644 --- a/frontend/lib/styles/font_styles.dart +++ b/frontend/lib/styles/font_styles.dart @@ -26,3 +26,18 @@ TextStyle titleStyle = const TextStyle( color: Colors.black, fontSize: 24, fontWeight: FontWeight.w400); + +TextStyle hintStyle = const TextStyle( + fontFamily: 'SF Pro', + color: Colors.grey, + fontSize: 15, + fontWeight: FontWeight.w400); + +TextStyle largerStyle = const TextStyle( + fontFamily: 'SF Pro', fontSize: 20, fontWeight: FontWeight.w400); + +TextStyle smallHintStyle = const TextStyle( + fontFamily: 'SF Pro', + color: Colors.grey, + fontSize: 10, + fontWeight: FontWeight.w400); diff --git a/frontend/lib/widgets/details/detail_description.dart b/frontend/lib/widgets/details/detail_description.dart new file mode 100644 index 0000000..a64c21a --- /dev/null +++ b/frontend/lib/widgets/details/detail_description.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:lp_task_scheduler/styles/font_styles.dart'; + +class DetailDescription extends StatelessWidget { + final String description; + const DetailDescription({Key? key, this.description = ""}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Description", style: hintStyle), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text(description), + ) + ], + ), + ), + Divider(), + ], + ), + ); + } +} diff --git a/frontend/lib/widgets/details/detail_row.dart b/frontend/lib/widgets/details/detail_row.dart new file mode 100644 index 0000000..5901266 --- /dev/null +++ b/frontend/lib/widgets/details/detail_row.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:lp_task_scheduler/styles/font_styles.dart'; + +class DetailRow extends StatelessWidget { + final IconData? icon; + final String label; + final String? data; + final String? points; + final double size; + + const DetailRow( + {this.icon, + required this.label, + this.data, + this.points, + this.size = 30, + Key? key}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0), + child: Column( + children: [ + Row( + children: [ + MaterialButton( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon(icon, size: size), + ), + onPressed: () {}, + shape: CircleBorder(side: BorderSide(color: Colors.deepOrange)), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text(label, style: hintStyle), + Text(data ?? '', style: largerStyle), + ], + ) + ], + ), + Divider(), + ], + ), + ); + } +} diff --git a/frontend/lib/widgets/details/finish_button.dart b/frontend/lib/widgets/details/finish_button.dart new file mode 100644 index 0000000..bc3fcb8 --- /dev/null +++ b/frontend/lib/widgets/details/finish_button.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:lp_task_scheduler/styles/font_styles.dart'; + +typedef void OnPressed(); + +class FinishButton extends StatelessWidget { + final OnPressed onPressed; + const FinishButton({Key? key, required this.onPressed}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MaterialButton( + onPressed: onPressed, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + ), + child: FractionallySizedBox( + widthFactor: 1, + child: Padding( + padding: const EdgeInsets.only(top: 8.0, bottom: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(100), + color: Colors.green, + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Icon(Icons.check, color: Colors.white, size: 20), + )), + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Text("Mark Finished", style: largerStyle), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/frontend/lib/widgets/details/task_details.dart b/frontend/lib/widgets/details/task_details.dart new file mode 100644 index 0000000..fc6c57d --- /dev/null +++ b/frontend/lib/widgets/details/task_details.dart @@ -0,0 +1,91 @@ +import 'dart:developer'; + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:lp_task_scheduler/styles/font_styles.dart'; +import 'package:lp_task_scheduler/widgets/details/detail_description.dart'; +import 'package:lp_task_scheduler/widgets/details/detail_row.dart'; +import 'package:lp_task_scheduler/widgets/details/finish_button.dart'; +import 'package:lp_task_scheduler/widgets/details/task_owner.dart'; +import 'package:lp_task_scheduler/widgets/new_task_panel.dart'; + +import '../assign_dropdown.dart'; +import '../date_panel.dart'; + +class TaskDetails extends StatefulWidget { + final DocumentSnapshot? ds; + TaskDetails({this.ds, Key? key}) : super(key: key); + @override + State createState() => _TaskDetailsState(); +} + +class _TaskDetailsState extends State { + ViewState _viewState = ViewState.standard; + DateFormat formatter = DateFormat('yyyy-MM-dd'); + + void setViewState(ViewState state) { + setState(() { + _viewState = state; + }); + } + + void completeTask() { + widget.ds!.reference.update({"status": "complete"}); + } + + @override + Widget build(BuildContext context) { + if (widget.ds == null || !widget.ds!.exists) { + return Container(); + } + dynamic data = widget.ds!.data(); + print(data.toString()); + DateTime date = DateTime.parse(data["dueDate"].toDate().toString()); + print(data); + return Scaffold( + appBar: AppBar( + title: Text('Task Details'), + ), + body: Padding( + padding: const EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 8.0, top: 8.0), + child: Text(data["title"], style: titleStyle), + ), + Column(children: [ + DetailRow( + icon: Icons.person, + label: "Assigned To", + data: data["assignedTo"][0]), + DetailRow( + icon: Icons.calendar_today, + label: "Due:", + data: formatter.format(date)), + DetailRow( + icon: Icons.star_border_rounded, + label: "Points", + data: data["points"].toString()), + ]), + DetailDescription( + description: data["description"], + ), + Center(child: FinishButton( + onPressed: () { + completeTask(); + }, + )), + Spacer(), + TaskOwner( + owner: data["owner"] ?? "unknown", + ) + ], + ), + ), + ); + } +} diff --git a/frontend/lib/widgets/details/task_owner.dart b/frontend/lib/widgets/details/task_owner.dart new file mode 100644 index 0000000..e9ecc35 --- /dev/null +++ b/frontend/lib/widgets/details/task_owner.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'package:lp_task_scheduler/styles/font_styles.dart'; + +class TaskOwner extends StatelessWidget { + final String owner; + final DateTime? date; + const TaskOwner({Key? key, required this.owner, this.date}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(bottom: 20), + child: Container( + height: 50, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(30), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 1, + blurRadius: 5, + offset: Offset(0, 3), // changes position of shadow + ), + ], + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Container( + // This is hacky, need help fixing + decoration: BoxDecoration( + color: Colors.blueGrey, + borderRadius: BorderRadius.circular(30), + ), + child: const Padding( + padding: EdgeInsets.only(top: 10), + child: Image( + width: 50, + height: 50, + fit: BoxFit.cover, + image: AssetImage('lib/assets/icons/homelogo.png')), + ), + width: 50, + height: 50, + ), + Padding( + padding: const EdgeInsets.fromLTRB(8.0, 16, 8, 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("Task created by $owner", style: mainStyle), + Text("1 week ago", style: smallHintStyle), + ], + ), + ) + ], + ), + ), + ); + } +} diff --git a/frontend/lib/widgets/interactive_task.dart b/frontend/lib/widgets/interactive_task.dart index 8f4bdd3..7f026fc 100644 --- a/frontend/lib/widgets/interactive_task.dart +++ b/frontend/lib/widgets/interactive_task.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:lp_task_scheduler/widgets/task_details.dart'; +import 'package:lp_task_scheduler/widgets/details/task_details.dart'; import 'package:lp_task_scheduler/widgets/touchable_opacity.dart'; import '../src/task.dart'; import 'package:firebase_core/firebase_core.dart'; diff --git a/frontend/lib/widgets/task_details.dart b/frontend/lib/widgets/task_details.dart deleted file mode 100644 index 369b750..0000000 --- a/frontend/lib/widgets/task_details.dart +++ /dev/null @@ -1,83 +0,0 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:lp_task_scheduler/styles/font_styles.dart'; -import 'package:lp_task_scheduler/widgets/new_task_panel.dart'; - -import 'assign_dropdown.dart'; -import 'date_panel.dart'; - -class TaskDetails extends StatefulWidget { - final DocumentSnapshot? ds; - TaskDetails({this.ds, Key? key}) : super(key: key); - @override - State createState() => _TaskDetailsState(); -} - -class _TaskDetailsState extends State { - ViewState _viewState = ViewState.standard; - - void setViewState(ViewState state) { - setState(() { - _viewState = state; - }); - } - - void completeTask() { - widget.ds!.reference.update({"status": "complete"}); - } - - @override - Widget build(BuildContext context) { - if (widget.ds == null || !widget.ds!.exists) { - return Container(); - } - dynamic data = widget.ds!.data(); - DateTime date = DateTime.parse(data["dueDate"].toDate().toString()); - print(data); - return Scaffold( - appBar: AppBar( - title: Text('Task Details'), - ), - body: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(data["title"], style: titleStyle), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - AssignDropdown( - "ch3p51@gmail.com", (String n) {}, "Unassigned", null), - TextButton.icon( - icon: const Icon(Icons.calendar_today), - label: Text('Due ${DateFormat('MMM dd yyyy').format(date)}'), - onPressed: () { - setViewState(ViewState.date); - }, - ), - ], - ), - Center( - child: Text(data["points"] != null - ? "Points: ${data["points"]}" - : "Points: ${1}"), - ), - Center( - child: Text(data["description"] != null - ? "Description: ${data["description"]}" - : "Description: ${'Add a description'}"), - ), - ElevatedButton( - onPressed: () { - completeTask(); - print("completedTask"); - }, - child: Text("Mark as Completed")) - ], - )), - ); - } -} From 3889e0908d723a6d1eaeccc7b1c079b91069135b Mon Sep 17 00:00:00 2001 From: TrevorFlanigan Date: Tue, 8 Mar 2022 01:01:56 -0800 Subject: [PATCH 4/4] catch missing data cases --- frontend/lib/widgets/details/task_details.dart | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frontend/lib/widgets/details/task_details.dart b/frontend/lib/widgets/details/task_details.dart index fc6c57d..16290da 100644 --- a/frontend/lib/widgets/details/task_details.dart +++ b/frontend/lib/widgets/details/task_details.dart @@ -61,7 +61,9 @@ class _TaskDetailsState extends State { DetailRow( icon: Icons.person, label: "Assigned To", - data: data["assignedTo"][0]), + data: data["assignedTo"] != null + ? data["assignedTo"][0] + : "Unassigned"), DetailRow( icon: Icons.calendar_today, label: "Due:", @@ -69,7 +71,8 @@ class _TaskDetailsState extends State { DetailRow( icon: Icons.star_border_rounded, label: "Points", - data: data["points"].toString()), + data: + data["points"] != null ? data["points"].toString() : "1"), ]), DetailDescription( description: data["description"],