import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'main.dart' as Main; import 'newActivity.dart'; import 'Data.dart'; import 'User.dart' as User; class Activities extends StatefulWidget { const Activities({Key? key}) : super(key: key); @override _ActivitiesState createState() => _ActivitiesState(); } class _ActivitiesState extends State { //late ProgressDialog progressDialog; 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(); //init(context); } @override void dispose() { // TODO: implement dispose super.dispose(); _focus.removeListener(_onFocusChange); _focus.dispose(); } void UpdateList() async { try { //progressDialog.show(max: 100, msg: 'Loading Activities'); } catch (e) {} await User.refreshUserData(); setState(() {}); try { // progressDialog.update(value: 100); } catch (e) {} } @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()); }, label: Text("New Activity"), icon: Icon(Icons.add)), appBar: AppBar( 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: () { UpdateList(); setState(() { }); }, child: Icon(Icons.refresh, size: 30), ) ], ), ], )), drawer: Main.navDrawer(context, 2), body: Container( padding: EdgeInsets.all(0), child: SingleChildScrollView( child: Column( children: PrintTasks(), )))); } List PrintTasks() { List _tasks = []; print('Priting cats : ' + User.taskTypes.length.toString()); String lastDate = ""; DateFormat dFormat = DateFormat("MM/dd"); Map productivtyActs = {}; Map unproductivtyActs = {}; Map totalMinutes = {}; 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) { totalMinutes[thisDate] = thisMinutes; } } else { totalMinutes.putIfAbsent(thisDate, () => thisMinutes); } if (element.taskType.cat?.productive ?? false) { if (productivtyActs.containsKey(thisDate)) { productivtyActs[thisDate] = (productivtyActs[thisDate]! + thisMinutes); } else { productivtyActs.putIfAbsent(thisDate, () => thisMinutes); } } else { if (unproductivtyActs.containsKey(thisDate)) { unproductivtyActs[thisDate] = (unproductivtyActs[thisDate]! + thisMinutes); } else { unproductivtyActs.putIfAbsent(thisDate, () => thisMinutes); } } } 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; int unProdActs = unproductivtyActs[thisDate] ?? 0; _tasks.add(DateSeperator(thisDate, prodActs, unProdActs)); lastDate = thisDate; } String name = element.taskType.name; if (element.taskType.cat == null) { print('Got some null cat : ${element.taskType.name}'); } else { Color color = Main.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); // print('Activity : ${name} ,sTime: ${element.startTime}, eTime: ${element.endTime}'); _tasks.add(task); } } return _tasks; } Widget DateSeperator(date, prodActs, unprodActs) { double prodPercentage = (prodActs / (prodActs + unprodActs)) * 100; return Padding( padding: const EdgeInsets.fromLTRB(0, 20, 10, 0), child: Column( children: [ Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Icon(Icons.remove_circle_outline), SizedBox( width: 10, ), Text( date, style: TextStyle(fontSize: 18), ), ], ), Row( children: [ Row( children: [ Container( child: Align( child: FittedBox(fit: BoxFit.fitWidth,child: Text(Main.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(Main.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), // child: Container( // alignment: Alignment.center, // height: 25.0, // width: 200, // child: Text( // "Productivity : ${prodPercentage.toStringAsFixed(1)}%", // style: TextStyle(fontWeight: FontWeight.bold),), // // ), // ), ], ) ], ), ); } bool selecting = false; 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); var _timeSpan = eTime.difference(sTime); String timeSpan = ((_timeSpan.inHours > 0) ? _timeSpan.inHours.toString() + 'h ' : '') + ((_timeSpan.inMinutes % 60 > 0) ? (_timeSpan.inMinutes % 60).toString() + 'm' : ''); return Row(children: [ // Container(), (selecting) ? Checkbox( value: selectedActivities.contains(activity), onChanged: (value) { print('selected $name'); OnItemSelected(activity); setState(() {}); }) : Container(padding: EdgeInsets.fromLTRB(10, 0, 5, 0), child: SizedBox(width: 1, height: 100, child: Container(color: Colors.white))), Expanded( child: Column(children: [ 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.ellipsis, ) ]), // 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())], )), ]), ), ]); } void OnItemSelected(Activity activity) { if (!selectedActivities.contains(activity)) { selectedActivities.add(activity); } else { selectedActivities.remove(activity); } } void DeleteSelectedTasks() async { //progressDialog.show(max: 100, msg: 'Deleteing ${selectedActivities.length} Activities'); selectedActivities.forEach((element) async { await User.UserOperations.deleteActivity(element, bulk: true); }); await Future.delayed(Duration(seconds: 2)); await User.UserOperations.executeQueries(); await User.updateActList(); selectedActivities = []; selecting = false; setState(() { // progressDialog.update(value: 100); }); } } List selectedActivities = [];