Todo basics added
This commit is contained in:
337
lib/NewTodo.dart
Normal file
337
lib/NewTodo.dart
Normal file
@@ -0,0 +1,337 @@
|
||||
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<NewTodo> {
|
||||
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<String, TaskType?> taskTypes = <String, TaskType?>{};
|
||||
Map<String, TaskType?> getActivities() {
|
||||
Map<String, TaskType?> _cats = <String, TaskType?>{};
|
||||
_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<String> 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<String>(
|
||||
dropdownColor: Color(0xFF222222),
|
||||
iconSize: 30,
|
||||
elevation: 10,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
value: selectedCat,
|
||||
isExpanded: true,
|
||||
items: getActivities().keys.map<DropdownMenuItem<String>>((String value) {
|
||||
print(value);
|
||||
return DropdownMenuItem<String>(
|
||||
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<String>(
|
||||
dropdownColor: Color(0xFF222222),
|
||||
iconSize: 30,
|
||||
elevation: 10,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
value: selectedStep,
|
||||
isExpanded: true,
|
||||
items: steps.map<DropdownMenuItem<String>>((String value) {
|
||||
print(value);
|
||||
return DropdownMenuItem<String>(
|
||||
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;
|
||||
},
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user