Show overlapping times
This commit is contained in:
parent
80f942fd1e
commit
d98fa17c91
|
|
@ -352,6 +352,35 @@ abstract class TaskEntity extends Object
|
||||||
return isValid && countRunning <= 1;
|
return isValid && countRunning <= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List get getInvalidTimeIndices {
|
||||||
|
final times = getTaskTimes();
|
||||||
|
DateTime lastDateTime = DateTime(2000);
|
||||||
|
|
||||||
|
final indices = <int>[];
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
times.forEach((time) {
|
||||||
|
final startDate = time.startDate;
|
||||||
|
final endDate = time.endDate;
|
||||||
|
|
||||||
|
if (time.isRunning) {
|
||||||
|
//
|
||||||
|
} else {
|
||||||
|
if (startDate.isBefore(lastDateTime) || startDate.isAfter(endDate)) {
|
||||||
|
indices.add(counter);
|
||||||
|
}
|
||||||
|
if (endDate.isBefore(startDate) || endDate.isBefore(lastDateTime)) {
|
||||||
|
indices.add(counter);
|
||||||
|
}
|
||||||
|
lastDateTime = lastDateTime.isAfter(endDate) ? lastDateTime : endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
});
|
||||||
|
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
|
|
||||||
bool get isRunning {
|
bool get isRunning {
|
||||||
final taskTimes = getTaskTimes();
|
final taskTimes = getTaskTimes();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,10 +123,12 @@ class _TaskEditDesktopState extends State<TaskEditDesktop> {
|
||||||
final client = state.clientState.get(task.clientId);
|
final client = state.clientState.get(task.clientId);
|
||||||
final showEndDate = company.showTaskEndDate;
|
final showEndDate = company.showTaskEndDate;
|
||||||
final taskTimes = task.getTaskTimes(sort: false);
|
final taskTimes = task.getTaskTimes(sort: false);
|
||||||
|
|
||||||
if (!taskTimes.any((taskTime) => taskTime.isEmpty)) {
|
if (!taskTimes.any((taskTime) => taskTime.isEmpty)) {
|
||||||
taskTimes.add(TaskTime().rebuild((b) => b..startDate = null));
|
taskTimes.add(TaskTime().rebuild((b) => b..startDate = null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final overlapping = task.getInvalidTimeIndices;
|
||||||
final rateLabel = localization.rate +
|
final rateLabel = localization.rate +
|
||||||
' • ' +
|
' • ' +
|
||||||
formatNumber(
|
formatNumber(
|
||||||
|
|
@ -413,8 +415,13 @@ class _TaskEditDesktopState extends State<TaskEditDesktop> {
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 4),
|
padding: const EdgeInsets.only(top: 4),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: Icon(Icons.clear),
|
icon: Icon(
|
||||||
tooltip: localization.remove,
|
Icons.clear,
|
||||||
|
color: overlapping.contains(index) ? Colors.red : null,
|
||||||
|
),
|
||||||
|
tooltip: overlapping.contains(index)
|
||||||
|
? localization.invalidTime
|
||||||
|
: localization.remove,
|
||||||
onPressed: taskTimes[index].isEmpty
|
onPressed: taskTimes[index].isEmpty
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ class _TaskEditTimesState extends State<TaskEditTimes> {
|
||||||
final viewModel = widget.viewModel;
|
final viewModel = widget.viewModel;
|
||||||
final task = viewModel.task;
|
final task = viewModel.task;
|
||||||
final taskTimes = task.getTaskTimes();
|
final taskTimes = task.getTaskTimes();
|
||||||
|
final invalidTimes = task.getInvalidTimeIndices;
|
||||||
final taskTime = viewModel.taskTimeIndex != null &&
|
final taskTime = viewModel.taskTimeIndex != null &&
|
||||||
taskTimes.length > viewModel.taskTimeIndex
|
taskTimes.length > viewModel.taskTimeIndex
|
||||||
? taskTimes[viewModel.taskTimeIndex]
|
? taskTimes[viewModel.taskTimeIndex]
|
||||||
|
|
@ -68,15 +69,18 @@ class _TaskEditTimesState extends State<TaskEditTimes> {
|
||||||
return HelpText(localization.clickPlusToAddTime);
|
return HelpText(localization.clickPlusToAddTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
final taskTimeWidgets = task
|
final sortedTaskTimes = task.getTaskTimes().toList().reversed.toList();
|
||||||
.getTaskTimes()
|
final taskTimeWidgets = <Widget>[];
|
||||||
.toList()
|
|
||||||
.reversed
|
for (var i = 0; i < sortedTaskTimes.length; i++) {
|
||||||
.map<Widget>((taskTime) => TaskTimeListTile(
|
final taskTime = sortedTaskTimes[i];
|
||||||
task: task,
|
taskTimeWidgets.add(TaskTimeListTile(
|
||||||
taskTime: taskTime,
|
task: task,
|
||||||
onTap: (context) => _showTaskTimeEditor(taskTime, context),
|
taskTime: taskTime,
|
||||||
));
|
onTap: (context) => _showTaskTimeEditor(taskTime, context),
|
||||||
|
isValid: !invalidTimes.contains(sortedTaskTimes.length - i - 1),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
return ScrollableListView(
|
return ScrollableListView(
|
||||||
children: taskTimeWidgets.toList(),
|
children: taskTimeWidgets.toList(),
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,13 @@ class TaskTimeListTile extends StatelessWidget {
|
||||||
@required this.task,
|
@required this.task,
|
||||||
@required this.taskTime,
|
@required this.taskTime,
|
||||||
@required this.onTap,
|
@required this.onTap,
|
||||||
|
@required this.isValid,
|
||||||
});
|
});
|
||||||
|
|
||||||
final Function(BuildContext context) onTap;
|
final Function(BuildContext context) onTap;
|
||||||
final TaskEntity task;
|
final TaskEntity task;
|
||||||
final TaskTime taskTime;
|
final TaskTime taskTime;
|
||||||
|
final bool isValid;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
@ -51,7 +53,9 @@ class TaskTimeListTile extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
subtitle: Text(subtitle),
|
subtitle: Text(subtitle),
|
||||||
trailing: onTap != null ? Icon(Icons.navigate_next) : null,
|
trailing: onTap != null
|
||||||
|
? Icon(isValid ? Icons.navigate_next : Icons.error)
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
Divider(
|
Divider(
|
||||||
height: 1.0,
|
height: 1.0,
|
||||||
|
|
|
||||||
|
|
@ -200,6 +200,7 @@ class _TaskOverviewState extends State<TaskOverview> {
|
||||||
TaskTimeListTile(
|
TaskTimeListTile(
|
||||||
task: task,
|
task: task,
|
||||||
taskTime: taskTime,
|
taskTime: taskTime,
|
||||||
|
isValid: true,
|
||||||
onTap: (BuildContext context) =>
|
onTap: (BuildContext context) =>
|
||||||
viewModel.state.userCompany.canEditEntity(task)
|
viewModel.state.userCompany.canEditEntity(task)
|
||||||
? viewModel.onEditPressed(context, taskTime)
|
? viewModel.onEditPressed(context, taskTime)
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
static final Map<String, Map<String, String>> _localizedValues = {
|
static final Map<String, Map<String, String>> _localizedValues = {
|
||||||
'en': {
|
'en': {
|
||||||
// STARTER: lang key - do not remove comment
|
// STARTER: lang key - do not remove comment
|
||||||
|
'invalid_time': 'Invalid Time',
|
||||||
'client_shipping_state': 'Client Shipping State',
|
'client_shipping_state': 'Client Shipping State',
|
||||||
'client_shipping_city': 'Client Shipping City',
|
'client_shipping_city': 'Client Shipping City',
|
||||||
'client_shipping_postal_code': 'Client Shipping Postal Code',
|
'client_shipping_postal_code': 'Client Shipping Postal Code',
|
||||||
|
|
@ -74125,6 +74126,10 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
_localizedValues[localeCode]['client_shipping_country'] ??
|
_localizedValues[localeCode]['client_shipping_country'] ??
|
||||||
_localizedValues['en']['client_shipping_country'];
|
_localizedValues['en']['client_shipping_country'];
|
||||||
|
|
||||||
|
String get invalidTime =>
|
||||||
|
_localizedValues[localeCode]['invalid_time'] ??
|
||||||
|
_localizedValues['en']['invalid_time'];
|
||||||
|
|
||||||
// STARTER: lang field - do not remove comment
|
// STARTER: lang field - do not remove comment
|
||||||
|
|
||||||
String lookup(String key) {
|
String lookup(String key) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue