import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:intl/intl.dart'; import 'package:tasktracker/NewTask.dart'; import 'package:tasktracker/NotificationsManager.dart'; import 'Data.dart'; import 'Dialogs.dart'; import 'User.dart' as User; DateFormat dateFormat = DateFormat("yyyy-MM-dd"); DateFormat dateTimeFormat = DateFormat("yyyy-MM-dd HH:mm"); DateFormat durationFormat = DateFormat("HH:mm:ss"); class NewTodo extends StatefulWidget { NewTodo({Key? key, this.selectedTask, this.metadata, this.dueDate,this.notificationTime}) : super(key: key); late String? metadata; late String? selectedTask; late DateTime? dueDate; late DateTime? notificationTime; @override _NewActivity createState() => _NewActivity(selectedCat: selectedTask, metadata: metadata); } class _NewActivity extends State { late String init_selectedTask; _NewActivity({String? metadata, String? selectedCat, DateTime? DueDate, this.notificationTime}) { editing =selectedCat != null && DueDate !=null; dueDate = DueDate ?? DateTime.now().add(Duration(days: 1)); this.metadataController.text = metadata ?? ""; if(this.metadataController.text.contains('[') && this.metadataController.text.contains(']') ){ this.metadataController.text = this.metadataController.text.substring(this.metadataController.text.indexOf(']')+1); selectedStep = metadata!.substring(1,metadata!.indexOf(']')); }else{ selectedStep='None'; } this.init_selectedTask = this.selectedCat = selectedCat ?? User.taskTypes[0].name; print(" meta:$metadata, task: $selectedCat"); } TextEditingController metadataController = TextEditingController(); late String selectedCat; late DateTime dueDate; DateTime? notificationTime; bool editing = false; Map taskTypes = {}; Map getActivities() { Map _cats = {}; _cats.putIfAbsent("+Add New Task Type", () => null); if (User.taskTypes.isEmpty) { } else { print(User.taskTypes[0].name + " : " + selectedCat); } User.taskTypes.forEach((element) { String name = element.name; if (_cats.keys.toString().contains(element.name)) { } else { String displayName = (name + ((element.relatedProject != null) ? ' [${element.relatedProject!.name}]' : '')); _cats.putIfAbsent(displayName, () => element); } }); return _cats; } String? selectedStep = null; @override Widget build(BuildContext context) { taskTypes = getActivities(); bool canSelectStep = false; List steps = ['None']; if (taskTypes[selectedCat] != null) { if (taskTypes[selectedCat]!.relatedProject != null) { //Got a project. But is it multi step? if (taskTypes[selectedCat]!.relatedProject!.steps.isNotEmpty) { canSelectStep = true; bool matchesSelectedStep = false; taskTypes[selectedCat]!.relatedProject!.steps.forEach((element) { if (element.finishedDate == null) { steps.add(element.stepName); if (selectedStep == null) { selectedStep = element.stepName; matchesSelectedStep = true; } if (element.stepName == selectedStep) { matchesSelectedStep = true; } } }); if (!matchesSelectedStep) { selectedStep = steps[0]; } } } } return Scaffold( appBar: AppBar(title: Text((editing) ? 'Edit To-Do' : 'New To-Do')), body: Column(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 9, child: SingleChildScrollView( scrollDirection: Axis.vertical, child: Padding( padding: EdgeInsets.fromLTRB(20, 10, 20, 10), 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.black12, borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.grey, width: 2)), child: DropdownButton( dropdownColor: Color(0xFF222222), iconSize: 30, elevation: 10, borderRadius: BorderRadius.circular(10), value: selectedCat, isExpanded: true, items: getActivities().keys.map>((String value) { print(value); return DropdownMenuItem( value: value, child: Text(value), ); }).toList(), onChanged: (String? _value) { if (_value == '+Add New Task Type') { Navigator.of(context).push(MaterialPageRoute(builder: (context) => NewTask())).then((val) { setState(() {}); }); } else { selectedCat = _value ?? 'n/a'; } setState(() {}); })), if (canSelectStep) Container(padding: EdgeInsets.all(10), child: Text('Step')), if (canSelectStep) Container( padding: EdgeInsets.symmetric(horizontal: 12, vertical: 1), decoration: BoxDecoration( color: Colors.black12, borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.grey, width: 2)), child: DropdownButton( dropdownColor: Color(0xFF222222), iconSize: 30, elevation: 10, borderRadius: BorderRadius.circular(10), value: selectedStep, isExpanded: true, items: steps.map>((String value) { print(value); return DropdownMenuItem( value: value, child: Text(value), ); }).toList(), onChanged: (String? _value) { selectedStep = _value; setState(() {}); })), Container( padding: EdgeInsets.all(10), child: Column( children: [ TextField( controller: metadataController, decoration: InputDecoration( hintText: 'Description (required)', filled: true, border: OutlineInputBorder(borderRadius: BorderRadius.circular(20))), ), ], )), Container( child: Divider( )), ListTile( leading: FaIcon(FontAwesomeIcons.calendarDay), title: Text('Due Date'), subtitle: Text('When do you want to do this?'), onTap:(){setState(() { DatePicker.showDatePicker(context, showTitleActions: true, onChanged: (date) { // print('change $date'); }, onConfirm: (date) { setState(() { dueDate=date; }); }, currentTime: dueDate, locale: LocaleType.en); });} , trailing: InkWell( child:Text(dateFormat.format(dueDate), style: TextStyle(color: Colors.blue)) ), ), Divider(), ListTile( title: Text('Notification'), leading: FaIcon((notificationTime==null) ?FontAwesomeIcons.bellSlash :FontAwesomeIcons.bell), trailing: Switch.adaptive(value: notificationTime!=null, onChanged: (val){ if(notificationTime==null){ notificationTime = DateTime.now().add(Duration(days: 1)); }else{ notificationTime = null; } setState(() { }); }), ) ]), ListTile( enabled: notificationTime!=null, leading: FaIcon(FontAwesomeIcons.clock), title: Text('Notify me at'), subtitle: Text('When do you want to do this?'), onTap:(){setState(() { DatePicker.showDateTimePicker(context, showTitleActions: true, onChanged: (date) { // print('change $date'); }, onConfirm: (date) { setState(() { notificationTime=date; }); }, currentTime: notificationTime, locale: LocaleType.en); });} , trailing: InkWell( child:Text(dateTimeFormat.format(notificationTime ?? DateTime.now()), style: TextStyle(color: Colors.blue)) ), ), ], )), ), ), 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 Todo', 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 { if(metadataController.text.isEmpty){ Dialogs.showAlertDialog(context, 'Invalid data', 'Please enter description to add new todo'); return; } await User.UserOperations.addTodo(selectedCat, metadataController.text, dueDate, notificationTime); Navigator.of(context).pop(); } void edit_action() async { } } 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; }, ); }