This repository has been archived on 2022-04-20. You can view files and clone it, but cannot push or open issues or pull requests.
app/lib/pages/list/task_edit.dart

234 lines
9.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
import 'package:intl/intl.dart';
import 'package:vikunja_app/components/datetimePicker.dart';
import 'package:vikunja_app/global.dart';
import 'package:vikunja_app/models/label.dart';
import 'package:vikunja_app/models/task.dart';
import 'package:vikunja_app/theme/button.dart';
import 'package:vikunja_app/theme/buttonText.dart';
import 'package:vikunja_app/theme/constants.dart';
import 'package:vikunja_app/utils/repeat_after_parse.dart';
class TaskEditPage extends StatefulWidget {
final Task task;
TaskEditPage({this.task}) : super(key: Key(task.toString()));
@override
State<StatefulWidget> createState() => _TaskEditPageState();
}
class _TaskEditPageState extends State<TaskEditPage> {
final _formKey = GlobalKey<FormState>();
bool _loading = false;
final dateFormat = DateFormat("EEEE, MMMM d, yyyy 'at' h:mma");
int _parentTaskID, _priority, _repeatAfterValue;
DateTime _dueDate, _startDate, _endDate;
List<DateTime> _reminderDates;
String _text, _description, _repeatAfterType;
Duration _repeatAfter;
List<Task> _subtasks;
List<Label> _labels;
@override
Widget build(BuildContext ctx) {
_repeatAfterType = getRepeatAfterTypeFromDuration(widget.task.repeatAfter);
_repeatAfterValue = getRepeatAfterValueFromDuration(widget.task.repeatAfter);
return Scaffold(
appBar: AppBar(
title: Text('Edit Task'),
),
body: Builder(
builder: (BuildContext context) => SafeArea(
child: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.all(16.0),
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: TextFormField(
maxLines: null,
keyboardType: TextInputType.multiline,
initialValue: widget.task.text,
onSaved: (text) => _text = text,
validator: (text) {
if (text.length < 3 || text.length > 250) {
return 'The text needs to have between 3 and 250 characters.';
}
return null;
},
decoration: new InputDecoration(
labelText: 'Text',
border: OutlineInputBorder(),
),
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: TextFormField(
maxLines: null,
keyboardType: TextInputType.multiline,
initialValue: widget.task.description,
onSaved: (description) => _description = description,
validator: (description) {
if (description.length > 1000) {
return 'The description can have a maximum of 1000 characters.';
}
return null;
},
decoration: new InputDecoration(
labelText: 'Description',
border: OutlineInputBorder(),
),
),
),
VikunjaDateTimePicker(
icon: Icon(Icons.access_time),
label: 'Due Date',
initialValue: widget.task.dueDate,
onSaved: (duedate) => _dueDate = duedate,
),
VikunjaDateTimePicker(
label: 'Start Date',
initialValue: widget.task.startDate,
onSaved: (startDate) => _startDate = startDate,
),
VikunjaDateTimePicker(
label: 'End Date',
initialValue: widget.task.endDate,
onSaved: (endDate) => _endDate = endDate,
),
Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Row(
children: [
Expanded(
flex: 2,
child: TextFormField(
keyboardType: TextInputType.number,
initialValue: _repeatAfterValue == null
? null
: _repeatAfterValue.toString(),
onSaved: (repeatAfter) => _repeatAfter =
_makeDurationFromType(
repeatAfter, _repeatAfterType),
decoration: new InputDecoration(
labelText: 'Repeat after',
border: InputBorder.none,
icon: Icon(Icons.repeat),
),
),
),
Expanded(
child: DropdownButton<String>(
isExpanded: true,
value: _repeatAfterType,
onChanged: (String newValue) {
setState(() {
_repeatAfterType = newValue;
});
},
items: <String>[
'Hours',
'Days',
'Weeks',
'Months',
'Years'
].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
],
),
),
Builder(
builder: (context) => Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: FancyButton(
onPressed: !_loading
? () {
if (_formKey.currentState.validate()) {
Form.of(context).save();
_saveTask(context);
}
}
: null,
child: _loading
? CircularProgressIndicator()
: VikunjaButtonText('Save'),
))),
]),
),
),
),
);
}
_saveTask(BuildContext context) async {
setState(() => _loading = true);
// FIXME: is there a way we can update the task without creating a new task object?
// aka updating the existing task we got from context (setters?)
Task updatedTask = Task(
id: widget.task.id,
text: _text,
description: _description,
done: widget.task.done,
reminderDates: _reminderDates,
dueDate: _dueDate,
startDate: _startDate,
endDate: _endDate,
priority: _priority,
repeatAfter: _repeatAfter,
labels: _labels,
);
VikunjaGlobal.of(context).taskService.update(updatedTask).then((_) {
setState(() => _loading = false);
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('The task was updated successfully!'),
));
}).catchError((err) {
setState(() => _loading = false);
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('Something went wrong: ' + err.toString()),
action: SnackBarAction(
label: 'CLOSE',
onPressed: Scaffold.of(context).hideCurrentSnackBar),
),
);
});
}
_makeDurationFromType(String value, String type) {
// Return an empty duration if either of the values is not set
if (value == null || value == '' || type == null || type == '') {
return Duration();
}
int val = int.parse(value);
switch (type) {
case 'Hours':
return Duration(seconds: val * 60);
case 'Days':
return Duration(seconds: val * 60 * 24);
case 'Weeks':
return Duration(seconds: val * 60 * 24 * 7);
case 'Months':
return Duration(seconds: val * 60 * 24 * 7 * 30);
case 'Years':
return Duration(seconds: val * 60 * 24 * 7 * 365);
}
}
}