Settings page added
This commit is contained in:
@@ -17,64 +17,132 @@ class Activities extends StatefulWidget {
|
||||
late ProgressDialog progressDialog;
|
||||
|
||||
class _ActivitiesState extends State<Activities> {
|
||||
TextEditingController searchController = TextEditingController();
|
||||
FocusNode _focus = FocusNode();
|
||||
bool searching = false;
|
||||
|
||||
void _onFocusChange() {
|
||||
print("FOCUS CHANGED! : ${_focus.hasFocus}");
|
||||
|
||||
if(!_focus.hasFocus){
|
||||
searching=false;
|
||||
setState(() {
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
|
||||
_focus.addListener(_onFocusChange);
|
||||
UpdateList();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
_focus.removeListener(_onFocusChange);
|
||||
_focus.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
progressDialog = ProgressDialog(context: context);
|
||||
return Scaffold(
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () {
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(builder: (context) => NewActivity()))
|
||||
.then((value) => UpdateList());
|
||||
Navigator.of(context).push(MaterialPageRoute(builder: (context) => NewActivity())).then((value) => UpdateList());
|
||||
},
|
||||
label: Text("New Activity"),
|
||||
icon: Icon(Icons.add)),
|
||||
appBar: AppBar(
|
||||
title: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(children: [
|
||||
Icon(Icons.task, color: Theme.of(context).primaryColor),
|
||||
SizedBox(width: 10),
|
||||
Text('Activities')
|
||||
]),
|
||||
(selecting)
|
||||
? Row(children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
DeleteSelectedTasks();
|
||||
},
|
||||
child: Icon(
|
||||
Icons.delete,
|
||||
size: 30,
|
||||
)),
|
||||
SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
selecting = false;
|
||||
});
|
||||
},
|
||||
child: Icon(Icons.close, size: 30),
|
||||
)
|
||||
])
|
||||
: Container(),
|
||||
],
|
||||
)),
|
||||
title: (searching)
|
||||
? Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(onChanged: (text){setState(() {
|
||||
|
||||
});},controller: searchController, focusNode: _focus, decoration: InputDecoration(
|
||||
filled: true,
|
||||
),),
|
||||
),
|
||||
InkWell(
|
||||
onTap: (){searching=false;
|
||||
searchController.clear();
|
||||
setState(() {
|
||||
|
||||
});},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Icon(Icons.cancel),
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(children: [Icon(Icons.task, color: Theme.of(context).primaryColor), SizedBox(width: 10), Text('Activities')]),
|
||||
(selecting)
|
||||
? Row(children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
DeleteSelectedTasks();
|
||||
},
|
||||
child: Icon(
|
||||
Icons.delete,
|
||||
size: 30,
|
||||
)),
|
||||
SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
selecting = false;
|
||||
});
|
||||
},
|
||||
child: Icon(Icons.close, size: 30),
|
||||
)
|
||||
])
|
||||
: Row(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
searching = true;
|
||||
_focus.requestFocus();
|
||||
setState(() {
|
||||
|
||||
});
|
||||
},
|
||||
child: Icon(
|
||||
Icons.search,
|
||||
size: 30,
|
||||
)),
|
||||
SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
setState(() async {
|
||||
await User.refreshUserData();
|
||||
UpdateList();
|
||||
});
|
||||
},
|
||||
child: Icon(Icons.refresh, size: 30),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
)),
|
||||
drawer: navDrawer(context, 2),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
padding: EdgeInsets.all(0),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: PrintTasks(),
|
||||
@@ -102,12 +170,12 @@ class _ActivitiesState extends State<Activities> {
|
||||
Map<String, int> totalMinutes = <String, int>{};
|
||||
for (var element in User.activities) {
|
||||
String thisDate = dFormat.format(element.startTime);
|
||||
int thisMinutes= element.endTime.difference(element.startTime).inMinutes;
|
||||
if(totalMinutes.containsKey(thisDate)){
|
||||
if((totalMinutes[thisDate]??0) < thisMinutes){
|
||||
int thisMinutes = element.endTime.difference(element.startTime).inMinutes;
|
||||
if (totalMinutes.containsKey(thisDate)) {
|
||||
if ((totalMinutes[thisDate] ?? 0) < thisMinutes) {
|
||||
totalMinutes[thisDate] = thisMinutes;
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
totalMinutes.putIfAbsent(thisDate, () => thisMinutes);
|
||||
}
|
||||
|
||||
@@ -127,6 +195,14 @@ class _ActivitiesState extends State<Activities> {
|
||||
}
|
||||
print(productivtyActs);
|
||||
for (var element in User.activities) {
|
||||
if(searching){
|
||||
if(element.metadata!.toLowerCase().contains(searchController.text.toLowerCase()) || element.taskType.name.toLowerCase().contains(searchController.text.toLowerCase())){
|
||||
//Good to go
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
String thisDate = dFormat.format(element.startTime);
|
||||
if (thisDate != lastDate) {
|
||||
int prodActs = productivtyActs[thisDate] ?? 0;
|
||||
@@ -138,11 +214,9 @@ class _ActivitiesState extends State<Activities> {
|
||||
if (element.taskType.cat == null) {
|
||||
print('Got some null cat : ${element.taskType.name}');
|
||||
} else {
|
||||
Color color =
|
||||
HexColor.fromHex(element.taskType.cat?.color ?? '#000000');
|
||||
Color color = HexColor.fromHex(element.taskType.cat?.color ?? '#000000');
|
||||
bool productive = element.taskType.cat?.productive ?? true;
|
||||
Widget task = ActivityCard(context, name, element.startTime,
|
||||
element.endTime, productive, color, element, totalMinutes[thisDate] ?? 0);
|
||||
Widget task = ActivityCard(context, name, element.startTime, element.endTime, productive, color, element, totalMinutes[thisDate] ?? 0);
|
||||
_tasks.add(task);
|
||||
}
|
||||
}
|
||||
@@ -153,27 +227,55 @@ class _ActivitiesState extends State<Activities> {
|
||||
Widget DateSeperator(date, prodActs, unprodActs) {
|
||||
double prodPercentage = (prodActs / (prodActs + unprodActs)) * 100;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(10, 20, 10, 0),
|
||||
padding: const EdgeInsets.fromLTRB(0, 20, 10, 0),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
date,
|
||||
style: TextStyle(fontSize: 18),
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.remove_circle_outline),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Text(
|
||||
date,
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(child:Align(child:Text(MinutesToTimeString(prodActs)), alignment: Alignment.center,),width: (prodPercentage) * 1.7, height: 25,decoration: BoxDecoration(color: Colors.green,borderRadius: BorderRadius.horizontal(left: Radius.circular(10))),),
|
||||
Container(child:Align(child:Text(MinutesToTimeString(unprodActs)), alignment: Alignment.center,),width: (100-prodPercentage)* 1.7,height: 25,decoration: BoxDecoration(color: Colors.red,borderRadius: BorderRadius.horizontal(right: Radius.circular(10))),),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 10,),
|
||||
Text(prodPercentage.toStringAsFixed(1) + "%",style: TextStyle(color: Colors.green, fontWeight: FontWeight.bold,fontSize: 20))
|
||||
],)
|
||||
Row(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
child: Align(
|
||||
child: FittedBox(fit: BoxFit.fitWidth,child: Text(MinutesToTimeString(prodActs),)),
|
||||
alignment: Alignment.center,
|
||||
),
|
||||
width: (prodPercentage) * 1.7,
|
||||
height: 25,
|
||||
decoration: BoxDecoration(color: Colors.green, borderRadius: BorderRadius.horizontal(left: Radius.circular(10))),
|
||||
),
|
||||
Container(
|
||||
child: Align(
|
||||
child: Text(MinutesToTimeString(unprodActs)),
|
||||
alignment: Alignment.center,
|
||||
),
|
||||
width: (100 - prodPercentage) * 1.7,
|
||||
height: 25,
|
||||
decoration: BoxDecoration(color: Colors.red, borderRadius: BorderRadius.horizontal(right: Radius.circular(10))),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Text(prodPercentage.toStringAsFixed(1) + "%", style: TextStyle(color: Colors.green, fontWeight: FontWeight.bold, fontSize: 20))
|
||||
],
|
||||
)
|
||||
// CustomPaint(
|
||||
// painter: MyPlayerBar(100, prodPercentage.toInt(),
|
||||
// background: Colors.green, fill: Colors.deepOrange),
|
||||
@@ -195,20 +297,14 @@ class _ActivitiesState extends State<Activities> {
|
||||
}
|
||||
|
||||
bool selecting = false;
|
||||
Widget ActivityCard(BuildContext context, String name, DateTime sTime,
|
||||
DateTime eTime, bool productive, Color color, Activity activity,int totalMinutes) {
|
||||
Widget ActivityCard(BuildContext context, String name, DateTime sTime, DateTime eTime, bool productive, Color color, Activity activity, int totalMinutes) {
|
||||
DateFormat dateFormat = DateFormat("HH:mm");
|
||||
int thisMinutes = (activity.endTime.difference(activity.startTime).inMinutes);
|
||||
int timePercentage = ((thisMinutes / totalMinutes) * 100).toInt();
|
||||
// print("$thisMinutes / $totalMinutes");
|
||||
bool containsMetadata = ((activity.metadata ?? 'null') != 'null') &&
|
||||
((activity.metadata ?? '').isNotEmpty);
|
||||
// print("$thisMinutes / $totalMinutes");
|
||||
bool containsMetadata = ((activity.metadata ?? 'null') != 'null') && ((activity.metadata ?? '').isNotEmpty);
|
||||
var _timeSpan = eTime.difference(sTime);
|
||||
String timeSpan =
|
||||
((_timeSpan.inHours > 0) ? _timeSpan.inHours.toString() + 'h ' : '') +
|
||||
((_timeSpan.inMinutes % 60 > 0)
|
||||
? (_timeSpan.inMinutes % 60).toString() + 'm'
|
||||
: '');
|
||||
String timeSpan = ((_timeSpan.inHours > 0) ? _timeSpan.inHours.toString() + 'h ' : '') + ((_timeSpan.inMinutes % 60 > 0) ? (_timeSpan.inMinutes % 60).toString() + 'm' : '');
|
||||
return Row(children: [
|
||||
// Container(),
|
||||
(selecting)
|
||||
@@ -219,84 +315,77 @@ class _ActivitiesState extends State<Activities> {
|
||||
OnItemSelected(activity);
|
||||
setState(() {});
|
||||
})
|
||||
: Container(),
|
||||
: Container(padding: EdgeInsets.fromLTRB(10, 0, 5, 0), child: SizedBox(width: 1, height: 100, child: Container(color: Colors.white))),
|
||||
Expanded(
|
||||
child: Column(children: [
|
||||
Card(
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 0, 5, 0),
|
||||
child: Card(
|
||||
|
||||
// color: color,
|
||||
elevation: 20,
|
||||
shadowColor: color,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
//Open Respective Category
|
||||
if (selecting) {
|
||||
OnItemSelected(activity);
|
||||
}
|
||||
setState(() {});
|
||||
},
|
||||
onLongPress: () {
|
||||
print('gonna delete');
|
||||
selecting = !selecting;
|
||||
selectedActivities = [activity];
|
||||
setState(() {});
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(15),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(children: [
|
||||
Text(name + " [$timeSpan]",
|
||||
style: TextStyle( fontSize: 17)),
|
||||
if (containsMetadata)
|
||||
Icon(Icons.arrow_forward_outlined, size: 20,),
|
||||
if (containsMetadata)
|
||||
Text(activity.metadata ?? '',overflow: TextOverflow.clip,)
|
||||
]),
|
||||
|
||||
// Icon(Icons.analytics, color: color, size: 20,),
|
||||
// color: color,
|
||||
elevation: 20,
|
||||
shadowColor: color,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
//Open Respective Category
|
||||
if (selecting) {
|
||||
OnItemSelected(activity);
|
||||
}
|
||||
setState(() {});
|
||||
},
|
||||
onLongPress: () {
|
||||
print('gonna delete');
|
||||
selecting = !selecting;
|
||||
selectedActivities = [activity];
|
||||
setState(() {});
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(15),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Row(children: [
|
||||
Text(name + " [$timeSpan]", style: TextStyle(fontSize: 17)),
|
||||
if (containsMetadata)
|
||||
Icon(
|
||||
Icons.arrow_forward_outlined,
|
||||
size: 20,
|
||||
),
|
||||
if (containsMetadata)
|
||||
Text(
|
||||
activity.metadata ?? '',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
)
|
||||
]),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(dateFormat.format(sTime) +
|
||||
" - " +
|
||||
dateFormat.format(eTime)),
|
||||
SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: (productive)
|
||||
? Colors.green
|
||||
: Colors.red),
|
||||
child: Text(
|
||||
activity.taskType.cat?.name ?? 'n/a'))
|
||||
// Icon(Icons.circle,
|
||||
// color: (productive)
|
||||
// ? Colors.green
|
||||
// : Colors.red)
|
||||
])
|
||||
],
|
||||
)))),
|
||||
|
||||
// Icon(Icons.analytics, color: color, size: 20,),
|
||||
]),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Text(dateFormat.format(sTime) + " - " + dateFormat.format(eTime)),
|
||||
SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 2),
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: (productive) ? Colors.green : Colors.red),
|
||||
child: Text(activity.taskType.cat?.name ?? 'n/a'))
|
||||
// Icon(Icons.circle,
|
||||
// color: (productive)
|
||||
// ? Colors.green
|
||||
// : Colors.red)
|
||||
])
|
||||
],
|
||||
)))),
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.fromLTRB(15, 0, 15, 10),
|
||||
height: 2,
|
||||
child:Row(children: [
|
||||
Expanded(flex:timePercentage ,child: Container(color:color)),
|
||||
Expanded(flex:100-timePercentage,child:Container())
|
||||
],)),
|
||||
child: Row(
|
||||
children: [Expanded(flex: timePercentage, child: Container(color: color)), Expanded(flex: 100 - timePercentage, child: Container())],
|
||||
)),
|
||||
]),
|
||||
),
|
||||
]);
|
||||
@@ -311,8 +400,7 @@ class _ActivitiesState extends State<Activities> {
|
||||
}
|
||||
|
||||
void DeleteSelectedTasks() async {
|
||||
progressDialog.show(
|
||||
max: 100, msg: 'Deleteing ${selectedActivities.length} Activities');
|
||||
progressDialog.show(max: 100, msg: 'Deleteing ${selectedActivities.length} Activities');
|
||||
selectedActivities.forEach((element) async {
|
||||
await User.UserOperations.deleteActivity(element, bulk: true);
|
||||
});
|
||||
@@ -328,7 +416,4 @@ class _ActivitiesState extends State<Activities> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
List<Activity> selectedActivities = [];
|
||||
|
||||
Reference in New Issue
Block a user