import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; import 'package:intl/intl.dart'; import 'package:tasktracker/main.dart'; import 'Data.dart'; import 'User.dart' as User; DateFormat dateFormat = DateFormat("yyyy-MM-dd HH:mm:ss"); DateFormat durationFormat = DateFormat("HH:mm:ss"); class NewActivity extends StatefulWidget { NewActivity({Key? key, this.selectedTask, this.sTime, this.eTime, this.metadata}) : super(key: key); late DateTime? sTime; late DateTime? eTime; late String? metadata; late String? selectedTask; @override _NewActivity createState() => _NewActivity(eTime: eTime, sTime: sTime,selectedCat: selectedTask, metadata: metadata); } class _NewActivity extends State { late DateTime init_sTime; late DateTime init_eTime; late String init_selectedTask; _NewActivity({DateTime? eTime, DateTime? sTime, String? metadata, String? selectedCat}){ editing = sTime != null && eTime!=null && selectedCat!=null; this.init_sTime=this.startTime = sTime ?? DateTime.now(); this.init_eTime=this.endTime = eTime ??DateTime.now().add(Duration(minutes: 30)); this.metadataController.text = metadata ?? ""; this.init_selectedTask=this.selectedCat = selectedCat ?? User.taskTypes[0].name; print("etime:$eTime, sTime:$sTime, meta:$metadata, task: $selectedCat"); } late DateTime startTime; late DateTime endTime; TextEditingController metadataController = TextEditingController(); late String selectedCat; bool editing=false; List getActivities(){ List _cats = []; print(User.taskTypes[0].name + " : " + selectedCat); User.taskTypes.forEach((element) { String name = element.name; if(_cats.contains(element.name)){ }else{ _cats.add(name);} }); return _cats; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text((editing) ? 'Edit Activity':'New Activity')), body:Column( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 9, child: SingleChildScrollView( scrollDirection: Axis.vertical, child: Padding( padding: EdgeInsets.fromLTRB(20, 50, 20, 50), child: Column( children: [ Column(children: [ Container( padding: EdgeInsets.all(10), child: Text('Task')), Container( padding: EdgeInsets.symmetric( horizontal: 12, vertical: 1), decoration: BoxDecoration( color: Colors.blueGrey, borderRadius: BorderRadius.circular(12), border: Border.all( color: Colors.grey, width: 2)), child: DropdownButton( dropdownColor: Colors.blueGrey, iconSize: 30, elevation: 10, borderRadius: BorderRadius.circular(10), value: selectedCat, isExpanded: true, items: getActivities().map>( (String value) { print(value); return DropdownMenuItem( value: value, child: Text(value), ); }).toList(), onChanged: (String? _value) { setState(() { selectedCat = _value ?? 'n/a'; }); })), Container( padding: EdgeInsets.all(10), child:Column( children: [ TextField( controller: metadataController, decoration: InputDecoration( hintText: 'Description (optional)', filled: true, border: OutlineInputBorder( borderRadius: BorderRadius.circular(20) ) ), ), ], ) ), Container( child: Divider( height: 30, )), Container( padding: EdgeInsets.all(10), child: Text('Start Time')), Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ QuickTimeButton('Last', Function: (){ if(User.activities.length > 0) { startTime= User.activities[0].endTime; } }) , Container( padding: EdgeInsets.symmetric( horizontal: 12, vertical: 1), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), border: Border.all( color: Colors.grey, width: 2)), child: MaterialButton( onPressed: () { setState(() { DatePicker.showDateTimePicker( context, showTitleActions: true, onChanged: (date) { // print('change $date'); }, onConfirm: (date) { setState(() { if(endTime.compareTo(date) < 0){ const snackBar = SnackBar( content: Text('You cannot start something after you ended it!'), ); ScaffoldMessenger.of(context).showSnackBar(snackBar); }else { startTime = date; } }); }, currentTime: startTime, locale: LocaleType.en); }); }, child: Text( dateFormat.format(startTime), style: TextStyle( color: Colors.blue)))), QuickTimeButton('Now', Function: (){ startTime = DateTime.now(); }) ], ), SizedBox( height: 10, ), Container( padding: EdgeInsets.all(10), child: Text('Ended Time')), Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Container(width: 60,), Container( padding: EdgeInsets.symmetric( horizontal: 12, vertical: 1), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), border: Border.all( color: Colors.grey, width: 2)), child: MaterialButton( onPressed: () { setState(() { DatePicker.showDateTimePicker( context, showTitleActions: true, onChanged: (date) { // print('change $date'); }, onConfirm: (date) { setState(() { if(startTime.compareTo(date) > 0){ const snackBar = SnackBar( content: Text('You cannot end something before you start it!'), ); ScaffoldMessenger.of(context).showSnackBar(snackBar); }else { endTime = date; } }); }, currentTime: endTime, locale: LocaleType.en); }); }, child: Text(dateFormat.format(endTime), style: TextStyle( color: Colors.blue)))), QuickTimeButton('Now', Function: (){ endTime = DateTime.now(); }) ], ), SizedBox( height: 30, ), Text('Duration : ' + _printDuration( endTime.difference(startTime)), style:TextStyle( fontSize: 20, )), Divider( height: 30, ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ], ) ]), ], )), ), ), Expanded( flex: 1, child: 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: () { 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: () { if(editing){ edit_action(); }else { add_action(); } }, child: Text((editing) ? 'Apply':'Add Activity', style: TextStyle(fontSize: 20))))), ], )), ) ])); } Widget QuickTimeButton(text, {Function}){ return InkWell( child: Container( padding:EdgeInsets.symmetric(horizontal: 15), height: 30, decoration:BoxDecoration( color: Colors.blueAccent, borderRadius: BorderRadius.circular(50) ), child:Align(child: Text(text),alignment: Alignment.center,) ), onTap: (){ Function(); setState(() { }); },); } void add_action() async{ print('adding Task Type : $selectedCat at $startTime - $endTime'); bool failed=false; await User.UserOperations.addActivity(selectedCat,startTime, endTime,metadata:metadataController.text, onOverlap: (overlapCount){ showAlertDialog(context, 'Error adding activity', 'Cannot add activity between ${dateFormat.format(startTime)} - ${dateFormat.format(endTime)}, $overlapCount activities are already added within this time range'); failed=true; }); if(!failed) { print("popping : ${navigatorKey.currentWidget?.toStringShort() ?? "n/a"}"); Navigator.of(navigatorKey.currentContext!).popUntil((route){ return route.isFirst; }); }else{ print("Failed adding new activity"); } } void edit_action() async{ print('adding Task Type : $selectedCat at $startTime - $endTime'); bool failed=false; await User.UserOperations.editActivity(init_sTime,init_eTime,selectedCat,startTime, endTime,metadata:metadataController.text, onOverlap: (overlapCount){ showAlertDialog(context, 'Error editing activity', 'Cannot add activity between ${dateFormat.format(startTime)} - ${dateFormat.format(endTime)}, $overlapCount activities are already added within this time range'); failed=true; }); if(!failed) { print("popping : ${navigatorKey.currentWidget?.toStringShort() ?? "n/a"}"); Navigator.of(navigatorKey.currentContext!).popUntil((route){ return route.isFirst; }); }else{ print("Failed editing new activity"); } } } 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; }, ); }