diameter/lib/screens/log/log_event_list.dart
2022-03-21 01:08:05 +01:00

387 lines
14 KiB
Dart

import 'package:diameter/utils/dialog_utils.dart';
import 'package:diameter/models/log_event.dart';
import 'package:diameter/models/settings.dart';
import 'package:diameter/screens/log/log_event_detail.dart';
import 'package:diameter/utils/date_time_utils.dart';
import 'package:flutter/material.dart';
import 'package:diameter/navigation.dart';
class LogEventListScreen extends StatefulWidget {
static const String routeName = '/log-events';
const LogEventListScreen({Key? key}) : super(key: key);
@override
_LogEventListScreenState createState() => _LogEventListScreenState();
}
class _LogEventListScreenState extends State<LogEventListScreen> {
List<LogEvent> _activeEvents = [];
late List<LogEvent> _logEvents;
final ScrollController _scrollController = ScrollController();
final TextEditingController _dateController = TextEditingController(text: '');
late DateTime _date;
bool _showActive = true;
String? swipeDirection;
@override
void initState() {
super.initState();
_date = DateTime.now();
_dateController.text = DateTimeUtils.displayDate(_date);
reload();
}
@override
void dispose() {
_scrollController.dispose();
_dateController.dispose();
super.dispose();
}
void reload({String? message}) {
setState(() {
_activeEvents = LogEvent.getAllActiveForTime(DateTime.now());
_logEvents = LogEvent.getAllForDate(_date);
});
setState(() {
if (message != null) {
var snackBar = SnackBar(
content: Text(message),
duration: const Duration(seconds: 2),
);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(snackBar);
}
});
}
void handleAddNewEvent() async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return _date.isAtSameMomentAs(DateTimeUtils.today())
? const LogEventDetailScreen()
: LogEventDetailScreen(
suggestedDate: _date,
);
},
),
).then((result) => reload(message: result?[0]));
}
void handleEditAction(LogEvent event) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LogEventDetailScreen(
id: event.id,
),
),
).then((result) => reload(message: result?[0]));
}
void onDelete(LogEvent logEvent) {
LogEvent.remove(logEvent.id);
reload(message: 'Event deleted');
}
void handleDeleteAction(LogEvent logEvent) async {
if (Settings.get().showConfirmationDialogOnDelete) {
DialogUtils.showConfirmationDialog(
context: context,
onConfirm: () => onDelete(logEvent),
message: 'Are you sure you want to delete this Event?',
);
} else {
onDelete(logEvent);
}
}
void onStop(LogEvent event) async {
event.endTime = DateTime.now();
LogEvent.put(event);
reload(message: 'Event ended');
}
void handleStopAction(LogEvent event) async {
if (Settings.get().showConfirmationDialogOnStopEvent) {
DialogUtils.showConfirmationDialog(
context: context,
onConfirm: () => onStop(event),
message: 'Are you sure you want to end this Event?',
confirmationLabel: 'END EVENT',
);
} else {
onStop(event);
}
}
void onChangeDate(DateTime? date) {
if (date != null) {
setState(() {
_date = DateTime(date.year, date.month, date.day);
_dateController.text = DateTimeUtils.displayDate(date);
});
reload();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Log Events'),
actions: <Widget>[
IconButton(
onPressed: () => onChangeDate(DateTime.now()),
icon: const Icon(Icons.today)),
IconButton(onPressed: reload, icon: const Icon(Icons.refresh))
],
),
drawer: const Navigation(currentLocation: LogEventListScreen.routeName),
body: GestureDetector(
onPanUpdate: (details) {
swipeDirection = details.delta.dx < 0 ? 'left' : 'right';
},
onPanEnd: (details) {
if (swipeDirection == null) {
return;
}
if (swipeDirection == 'right' &&
!_date.isAtSameMomentAs(DateTime(2000, 1, 1))) {
onChangeDate(_date.subtract(const Duration(days: 1)));
}
if (swipeDirection == 'left' &&
_date.add(const Duration(days: 1)).isBefore(DateTime.now())) {
onChangeDate(_date.add(const Duration(days: 1)));
}
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () => setState(() {
_showActive = !_showActive;
}),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Text(
'ACTIVE EVENTS',
style: Theme.of(context).textTheme.subtitle2,
textAlign: TextAlign.center,
),
),
Icon(_showActive ? Icons.expand_less : Icons.expand_more),
],
),
),
),
!_showActive
? Container()
: _activeEvents.isNotEmpty
? ListView.builder(
shrinkWrap: true,
padding: const EdgeInsets.all(10.0),
itemCount: _activeEvents.length,
itemBuilder: (context, index) {
LogEvent event = _activeEvents[index];
return Card(
child: ListTile(
onTap: () {
handleEditAction(event);
},
title: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Text(
DateTimeUtils.displayDateTime(event.time),
),
const SizedBox(width: 24),
Expanded(
child: Text(
(event.title ??
event.eventType.target?.value ??
'')
.toUpperCase(),
style:
Theme.of(context).textTheme.subtitle2,
),
),
],
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
event.hasEndTime && event.endTime == null
? IconButton(
icon: const Icon(
Icons.stop,
color: Colors.blue,
),
onPressed: () =>
handleStopAction(event),
)
: const SizedBox(width: 50),
IconButton(
icon: const Icon(
Icons.edit,
color: Colors.blue,
),
onPressed: () => handleEditAction(event),
),
IconButton(
icon: const Icon(
Icons.delete,
color: Colors.blue,
),
onPressed: () => handleDeleteAction(event),
),
],
),
),
);
},
)
: const Center(
child: Text('There are no Active Events!'),
),
const Padding(
padding: EdgeInsets.all(10.0),
child: Divider(),
),
Row(
children: [
IconButton(
onPressed: _date.isAtSameMomentAs(DateTime(2000, 1, 1))
? null
: () =>
onChangeDate(_date.subtract(const Duration(days: 1))),
icon: const Icon(Icons.arrow_back),
),
Expanded(
child: GestureDetector(
onTap: () async {
final newTime = await showDatePicker(
context: context,
initialDate: _date,
firstDate: DateTime(2000, 1, 1),
lastDate: DateTime.now().add(const Duration(days: 365)),
);
onChangeDate(newTime);
},
child: Text(
DateTimeUtils.displayDate(_date).toUpperCase(),
style: Theme.of(context).textTheme.subtitle2,
textAlign: TextAlign.center,
),
),
),
IconButton(
onPressed: _date
.add(const Duration(days: 1))
.isBefore(DateTime.now())
? () => onChangeDate(_date.add(const Duration(days: 1)))
: null,
icon: const Icon(Icons.arrow_forward),
),
],
),
Expanded(
child: _logEvents.isNotEmpty
? Scrollbar(
controller: _scrollController,
child: ListView.builder(
controller: _scrollController,
shrinkWrap: true,
padding: const EdgeInsets.all(10.0),
itemCount: _logEvents.length,
itemBuilder: (context, index) {
LogEvent event = _logEvents[index];
return Card(
child: ListTile(
onTap: () {
handleEditAction(event);
},
title: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Text(
DateTimeUtils.displayTime(event.isEndEvent
? event.endTime
: event.time),
),
const SizedBox(width: 24),
Expanded(
child: Text(
(event.title ??
event.eventType.target?.value ??
'')
.toUpperCase(),
style:
Theme.of(context).textTheme.subtitle2,
),
),
],
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
event.hasEndTime && event.endTime == null
? IconButton(
icon: const Icon(
Icons.stop,
color: Colors.blue,
),
onPressed: () =>
handleStopAction(event),
)
: const SizedBox(width: 50),
IconButton(
icon: const Icon(
Icons.edit,
color: Colors.blue,
),
onPressed: () => handleEditAction(event),
),
IconButton(
icon: const Icon(
Icons.delete,
color: Colors.blue,
),
onPressed: () => handleDeleteAction(event),
),
],
),
),
);
},
))
: const Center(
child: Text('There are no Events for that date!'),
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: handleAddNewEvent,
child: const Icon(Icons.add),
),
);
}
}