diff --git a/lib/Activities.dart b/lib/Activities.dart index aabfce4..0642e73 100644 --- a/lib/Activities.dart +++ b/lib/Activities.dart @@ -238,7 +238,7 @@ class _ActivitiesState extends State { //Check for gaps if(i < User.activities.length-1){ int gap = User.activities[i].trueStartTime.difference(User.activities[i+1].trueEndTime).inMinutes; - if(gap > 20) { + if(gap > 10) { Widget addGap = timeGap(User.activities[i].trueStartTime, User.activities[i+1].trueEndTime); _tasks.add(addGap); diff --git a/lib/DateTimeRangeCustom.dart b/lib/DateTimeRangeCustom.dart new file mode 100644 index 0000000..ba75b66 --- /dev/null +++ b/lib/DateTimeRangeCustom.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +int hourSelection = 1; +FixedExtentScrollController scrollController = FixedExtentScrollController(); +Future showDurationSelector(BuildContext context, {required Function(Duration) onChange, int? selectedHour}) async { + + hourSelection = selectedHour ?? 1; + + scrollController = FixedExtentScrollController(initialItem: hourSelection-1); + return showDialog( + context: context, + barrierDismissible: false, // user must tap button! + builder: (BuildContext context) { + + return StatefulBuilder( + builder:(context, setState) { + setState((){}); + return AlertDialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(30)), + backgroundColor: Colors.white10, + title: Align(alignment: Alignment.center, + child: const Text('Select Time Range')), + content: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + height: 150, + width: 50, + child: ListWheelScrollView( + // useMagnifier: true, + controller: scrollController, + diameterRatio: 1, + itemExtent: 30, + children: printHours(), + + onSelectedItemChanged: (index) { + hourSelection = index + 1; + setState(() {}); + //scrollController.jumpTo(index.toDouble()); + print("Changed to $index"); + }, + ), + + ), + Text(' Hours') + ], + ), + actions: [ + TextButton( + child: const Text('Select'), + onPressed: () { + onChange(Duration(hours: hourSelection)); + Navigator.of(context).pop(); + }, + ), + ], + ); + } + ); + }, + ); +} + + +List printHours(){ + List _hours = []; + for(int i = 0; i < 5000; i++){ + _hours.add(Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), color:(hourSelection-1==i) ? Colors.redAccent :null ),alignment:Alignment.center,width:50,child: Text((i+1).toString()))); + } + + return _hours; +} \ No newline at end of file diff --git a/lib/Dialogs.dart b/lib/Dialogs.dart index b1ac986..d6ea1dd 100644 --- a/lib/Dialogs.dart +++ b/lib/Dialogs.dart @@ -17,6 +17,8 @@ class Dialogs{ routeSettings: const RouteSettings(name: "Progress"), builder: (BuildContext context) { return AlertDialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)), + backgroundColor: Color(0xaa101010), title: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, diff --git a/lib/NewProject.dart b/lib/NewProject.dart new file mode 100644 index 0000000..6960f8d --- /dev/null +++ b/lib/NewProject.dart @@ -0,0 +1,418 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; +import 'package:intl/intl.dart'; +import 'package:flutter_colorpicker/flutter_colorpicker.dart'; +import 'User.dart' as User; +import 'Data.dart'; +import 'package:flutter_switch/flutter_switch.dart'; +import 'DateTimeRangeCustom.dart'; + +DateFormat dateFormat = DateFormat("yyyy-MM-dd HH:mm:ss"); +DateFormat durationFormat = DateFormat("HH:mm:ss"); + +class NewProject extends StatefulWidget { + const NewProject({Key? key}) : super(key: key); + + @override + _NewProjectState createState() => _NewProjectState(); +} + +List getCategoryNames() { + List _cats = []; + User.categories.forEach((element) { + String name = element.name; + _cats.add(name); + }); + return _cats; +} + +bool multiLine = true; +String selectedCat = User.categories[0].name; + +class _NewProjectState extends State { + TextEditingController nameController = TextEditingController(); + bool productive = true; + Color pickerColor = Colors.blue; + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('New Project')), + body: Container( + height: MediaQuery.of(context).size.height, + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SingleChildScrollView( + child: Padding( + padding: EdgeInsets.fromLTRB(20, 50, 20, 50), + child: Column( + children: [ + Container( + padding: EdgeInsets.all(0), + child: Text('Project Name')), + Container( + padding: EdgeInsets.all(10), + child: TextField( + controller: nameController, + decoration: InputDecoration( + hintText: + 'ex: Cool science project, Build a new game etc...', + border: OutlineInputBorder()), + ), + ), + Divider(), + Column(children: [ + Container( + padding: EdgeInsets.all(0), + child: Text('Related Category')), + Container( + margin: EdgeInsets.all(10), + padding: EdgeInsets.symmetric( + horizontal: 12, vertical: 1), + decoration: BoxDecoration( + color: Colors.white10, + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: Colors.grey, width: 2)), + child: DropdownButton( + dropdownColor: Colors.black, + iconSize: 30, + elevation: 10, + borderRadius: BorderRadius.circular(10), + value: selectedCat, + isExpanded: true, + items: getCategoryNames() + .map>( + (String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + onChanged: (String? _value) { + setState(() { + selectedCat = _value!; + }); + })), + Divider(), + Container( + padding: EdgeInsets.all(10), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text('This project is', + style: TextStyle(fontSize: 18)), + FlutterSwitch( + width: 130, + height: 35.0, + valueFontSize: 15.0, + toggleSize: 25.0, + toggleColor: Colors.white70, + activeTextColor: Colors.white, + inactiveTextColor: Colors.white, + value: multiLine, + borderRadius: 30.0, + showOnOff: true, + activeText: 'Multi step', + inactiveText: 'Single step', + activeColor: Colors.deepOrange, + activeIcon: Icon(Icons.linear_scale, + color: Colors.orange), + inactiveIcon: Icon(Icons.check, + color: Colors.green), + inactiveColor: Colors.green, + onToggle: (val) { + setState(() { + multiLine = val; + print( + "Multi=Step : $multiLine"); + }); + }, + ) + ])), + ]), + ], + ))), + Container( + padding: + EdgeInsets.symmetric(vertical: 10, horizontal: 20), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 5, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 10, vertical: 0), + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: Colors.red, + shape: StadiumBorder()), + onPressed: () { + setState(() { + Navigator.pop(context); + }); + }, + child: Text('Cancel', + style: TextStyle(fontSize: 20))))), + Expanded( + flex: 6, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 10, vertical: 0), + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: Colors.green, + shape: StadiumBorder()), + onPressed: () { + // add_action(); + if (nameController.text.length > 3) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => + NewProject2( + projectName: + nameController.text, + ))); + } else { + showAlertDialog(context, 'Really?', + 'Enter a valid name for this project!'); + } + }, + child: Text('Next', + style: TextStyle(fontSize: 20))))), + ], + )) + ]))); + } + + void pickColor(BuildContext context) => showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Pick Color for Category'), + content: Column(mainAxisSize: MainAxisSize.min, children: [ + MaterialPicker( + pickerColor: pickerColor, + onColorChanged: (color) { + setState(() { + pickerColor = color; + }); + }, + enableLabel: false, + portraitOnly: true, + ), + TextButton( + child: Text('Select', style: TextStyle(fontSize: 20)), + onPressed: () => Navigator.of(context).pop(), + ) + ]), + )); + + void add_action() async { + String catName = nameController.value.text; + + if (catName.length < 2) { + showAlertDialog(context, 'Category needs a name', + 'Please enter a name for this category'); + return; + } + var hex = '#${pickerColor.value.toRadixString(16)}'; + await User.UserOperations.addCategory(catName, hex, productive); + Navigator.of(context).popUntil((route) { + return route.isFirst; + }); + } +} + +String _printDuration(Duration duration) { + String twoDigits(int n) => n.toString().padLeft(2, "0"); + String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60)); + String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60)); + return "${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds"; +} + +showAlertDialog(BuildContext context, String title, String message) { + // set up the button + Widget okButton = TextButton( + child: Text("OK"), + onPressed: () { + Navigator.of(context).pop(); + }, + ); + + // set up the AlertDialog + AlertDialog alert = AlertDialog( + title: Text(title), + content: Text(message), + actions: [ + okButton, + ], + ); + + // show the dialog + showDialog( + context: context, + builder: (BuildContext context) { + return alert; + }, + ); +} + +class NewProject2 extends StatefulWidget { + NewProject2({Key? key, this.projectName}) : super(key: key); + late String? projectName; + @override + State createState() => _NewProject2State(pName: projectName); +} + +class _NewProject2State extends State { + int etaHours = 1; + DateTime deadline = DateTime.now().add(Duration(days:7)); + late String? projectName; + _NewProject2State({String? pName}) { + projectName = pName; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text(projectName ?? 'Error')), + body: Container( + height: MediaQuery.of(context).size.height, + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SingleChildScrollView( + child: Container( + padding: EdgeInsets.fromLTRB(20, 50, 20, 50), + child: (multiLine) + ? Column( + children: [ + Column( + children: [Text("eeeeeeee")], + ) + ], + ) + : Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.all(10), + child: Text( + "Estimated Time to reach target")), + InkWell( + onTap: () { + showDurationSelector(context,selectedHour: etaHours, onChange: (newVal){ + etaHours = newVal.inHours; + setState(() { + + }); + print("Selected $newVal"); + }); + }, + child: Container( + decoration: BoxDecoration( + color: Colors.white10, + borderRadius: + BorderRadius.circular(30), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 100, vertical: 10), + child: Text("$etaHours Hours"), + ), + ), + ), + SizedBox( + height: 20, + ), + Container( + padding: EdgeInsets.all(8), + child: Text("Deadline")), + InkWell( + onTap: () { + DatePicker.showDatePicker( + context, + showTitleActions: true, + minTime: DateTime.now(), + theme: DatePickerTheme(backgroundColor: Colors.white), + onChanged: (date) { + // print('change $date'); + }, onConfirm: (date) { + setState(() { + if(deadline.isAfter(DateTime.now())){ + deadline=date; + }else{ + showAlertDialog(context, 'Come on!', 'Deadline was passed?'); + } + }); + }, + currentTime: deadline, + locale: LocaleType.en); + setState(() { + + }); + }, + child: Container( + decoration: BoxDecoration( + color: Colors.white10, + borderRadius: + BorderRadius.circular(30), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 100, vertical: 10), + child: Text(DateFormat("MMMM dd yyyy").format(deadline)), + ), + ), + ), + ], + ))), + + Container( + padding: + EdgeInsets.symmetric(vertical: 10, horizontal: 20), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 5, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 10, vertical: 0), + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: Colors.red, + shape: StadiumBorder()), + onPressed: () { + setState(() { + Navigator.pop(context); + }); + }, + child: Text('Back', + style: TextStyle(fontSize: 20))))), + Expanded( + flex: 6, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 10, vertical: 0), + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: Colors.green, + shape: StadiumBorder()), + onPressed: () {}, + child: Text('Next', + style: TextStyle(fontSize: 20))))), + ], + )) + ]))); + } +} diff --git a/lib/Projects.dart b/lib/Projects.dart index 38425da..9985f24 100644 --- a/lib/Projects.dart +++ b/lib/Projects.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:tasktracker/NewProject.dart'; import 'User.dart' as User; import 'main.dart'; class Projects extends StatefulWidget { @@ -14,7 +15,7 @@ class _ProjectsState extends State { return SafeArea(child: Scaffold( floatingActionButton: FloatingActionButton.extended( onPressed: () { - // Navigator.of(context).push(MaterialPageRoute(builder: (context) => NewTodo())).then((value) => {User.refreshUserData().then((va) => {})}); + Navigator.of(context).push(MaterialPageRoute(builder: (context) => NewProject())).then((value) => {User.refreshUserData().then((va) => {})}); }, label: Text("New Project"), icon: Icon(Icons.add)), @@ -97,13 +98,4 @@ class _ProjectsState extends State { ] ); } - - Widget prioritySeperator(String text){ - return Padding( - padding: const EdgeInsets.fromLTRB(15,15,15,0), - child: Row( - children: [Text(text,style:TextStyle(fontSize: 18, color: Colors.grey))], - ), - ); - } } diff --git a/lib/User.dart b/lib/User.dart index ab87f0f..581150b 100644 --- a/lib/User.dart +++ b/lib/User.dart @@ -625,8 +625,8 @@ class UserOperations { Map queryBody = { 'username': username, 'device_id': await Settings.UUID(), - 'sTime': activity.startTime.toString(), - 'eTime': activity.endTime.toString(), + 'sTime': activity.trueStartTime.toString(), + 'eTime': activity.trueEndTime.toString(), }; //Add Query Map query = {Queries.colLink: 'delete_activity', Queries.colData: jsonEncode(queryBody)}; @@ -637,7 +637,7 @@ class UserOperations { //update Cache String deleteQuery = - "DELETE FROM Activities WHERE ${Activity.colStartTime}=datetime('${dFormat.format(activity.startTime)}') AND ${Activity.colEndTime}=datetime('${dFormat.format(activity.endTime)}')"; + "DELETE FROM Activities WHERE ${Activity.colStartTime}=datetime('${dFormat.format(activity.trueStartTime)}') AND ${Activity.colEndTime}=datetime('${dFormat.format(activity.trueEndTime)}')"; print("delteQuery : $deleteQuery"); await cacheDb.rawDelete(deleteQuery); diff --git a/lib/main.dart b/lib/main.dart index 1daa7ad..c120a2e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -84,7 +84,7 @@ class MyApp extends StatelessWidget { title: 'Task Tracker', themeMode: themeProvider.themeMode, theme: ThemeData(accentColor: Colors.redAccent, brightness: Brightness.light, primaryColor: Colors.amber, fontFamily: 'Noto-Sans'), - darkTheme: ThemeData(accentColor: Colors.redAccent, brightness: Brightness.dark, primaryColor: Colors.amber, fontFamily: 'Noto-Sans'), + darkTheme: ThemeData(backgroundColor: Colors.black,accentColor: Colors.redAccent, brightness: Brightness.dark, primaryColor: Colors.amber, fontFamily: 'Noto-Sans'), navigatorKey: navigatorKey, //home: const SplashScreen(), initialRoute: '/', diff --git a/lib/newActivity.dart b/lib/newActivity.dart index 5d45f9a..1b23c41 100644 --- a/lib/newActivity.dart +++ b/lib/newActivity.dart @@ -152,6 +152,7 @@ class _NewActivity extends State { setState(() { DatePicker.showDateTimePicker( context, + maxTime: endTime, showTitleActions: true, onChanged: (date) { // print('change $date'); @@ -205,6 +206,7 @@ class _NewActivity extends State { DatePicker.showDateTimePicker( context, showTitleActions: true, + minTime: startTime, onChanged: (date) { // print('change $date'); }, onConfirm: (date) { @@ -323,6 +325,9 @@ class _NewActivity extends State { } void add_action() async{ + if(startTime.isAfter(endTime)){ + showAlertDialog(context, 'Really?', 'Start time and end time doesnt make any sense'); + } print('adding Task Type : $selectedCat at $startTime - $endTime'); bool failed=false; await User.UserOperations.addActivity(selectedCat,startTime, endTime,metadata:metadataController.text, onOverlap: (overlapCount){ diff --git a/pubspec.lock b/pubspec.lock index ac77380..c4f2219 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -230,6 +230,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.1.0" + flutter_switch: + dependency: "direct main" + description: + name: flutter_switch + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.2" flutter_test: dependency: "direct dev" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 6073e9d..52c43b9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,7 @@ dependencies: flutter: sdk: flutter + flutter_switch: ^0.3.2 sqflite_common_ffi: ^2.1.0+2 connectivity_plus: ^2.2.1 flutter_spinkit: ^5.1.0