add information to log; separate log events from log entry
This commit is contained in:
parent
796265b048
commit
e42ad61f44
18
TODO
18
TODO
@ -9,22 +9,18 @@ MAIN TASKS:
|
|||||||
☐ replace active profile picking mode with simple dropdown
|
☐ replace active profile picking mode with simple dropdown
|
||||||
☐ indicate both the default rate and the currently active one (according to event)
|
☐ indicate both the default rate and the currently active one (according to event)
|
||||||
|
|
||||||
Log Overview:
|
|
||||||
☐ display more information
|
|
||||||
☐ apply target color settings to glucose
|
|
||||||
☐ total bolus and carbs per entry
|
|
||||||
|
|
||||||
Log Entry:
|
Log Entry:
|
||||||
☐ check for multiple active events with temporary basal/bolus profiles (smallest covered time frame counts)
|
☐ check for multiple active events with temporary basal/bolus profiles (smallest covered time frame counts)
|
||||||
☐ provide splitting functionality for overlapping events
|
☐ provide splitting functionality for overlapping events
|
||||||
☐ provide percentage functionality for delayed bolus
|
☐ provide percentage functionality for delayed bolus
|
||||||
☐ get rid of useless cancellation warnings
|
☐ get rid of useless cancellation warnings
|
||||||
|
|
||||||
|
Events:
|
||||||
|
☐ when adding an event later on, prompt if existing boli should be recalculated
|
||||||
|
☐ show event start AND end times in list
|
||||||
|
|
||||||
Settings:
|
Settings:
|
||||||
☐ add objectbox class and use instead of shared preferences
|
☐ add objectbox class and use instead of shared preferences
|
||||||
☐ add fields for preferred date and time formats
|
|
||||||
☐ add fields for glucose target (as map of cutoff glucose and colors)
|
|
||||||
☐ add option to hide warning dialogs on cancel or event stop
|
|
||||||
|
|
||||||
FUTURE TASKS:
|
FUTURE TASKS:
|
||||||
General/Framework:
|
General/Framework:
|
||||||
@ -39,14 +35,20 @@ FUTURE TASKS:
|
|||||||
☐ find a better way to work with multiple measurements (or disable it?)
|
☐ find a better way to work with multiple measurements (or disable it?)
|
||||||
Log Overview:
|
Log Overview:
|
||||||
☐ add pagination
|
☐ add pagination
|
||||||
|
☐ apply target color settings to glucose
|
||||||
Event Types:
|
Event Types:
|
||||||
☐ add colors as indicators for log entries (and later graphs in reports)
|
☐ add colors as indicators for log entries (and later graphs in reports)
|
||||||
☐ implement reminders as push notifications
|
☐ implement reminders as push notifications
|
||||||
Settings:
|
Settings:
|
||||||
|
☐ add fields for preferred date and time formats
|
||||||
|
☐ add fields for glucose target (as map of cutoff glucose and colors)
|
||||||
|
☐ add option to hide warning dialogs on cancel or event stop
|
||||||
☐ add option to hide extra customization options (ie. changing pre calculated values)
|
☐ add option to hide extra customization options (ie. changing pre calculated values)
|
||||||
☐ add setting for decimal places
|
☐ add setting for decimal places
|
||||||
|
|
||||||
Archive:
|
Archive:
|
||||||
|
✔ separate events from log entries @done(21-12-01 23:37) @project(MAIN TASKS.Events)
|
||||||
|
✔ show total bolus and carbs per entry @done(21-12-01 19:50) @project(MAIN TASKS.Log Overview)
|
||||||
✔ display boli correctly @done(21-11-30 04:14) @project(MAIN TASKS.Log Entry)
|
✔ display boli correctly @done(21-11-30 04:14) @project(MAIN TASKS.Log Entry)
|
||||||
✔ replace meal and glucose boli with logbolus entities @done(21-11-30 03:56) @project(MAIN TASKS.Log Entry)
|
✔ replace meal and glucose boli with logbolus entities @done(21-11-30 03:56) @project(MAIN TASKS.Log Entry)
|
||||||
✔ adjust/debug active events view @done(21-11-26 22:54) @project(MAIN TASKS.Log Overview)
|
✔ adjust/debug active events view @done(21-11-26 22:54) @project(MAIN TASKS.Log Overview)
|
||||||
|
@ -115,7 +115,7 @@ class _DateTimeFormFieldState extends State<DateTimeFormField> {
|
|||||||
context: context,
|
context: context,
|
||||||
initialDate: widget.date,
|
initialDate: widget.date,
|
||||||
firstDate: widget.minDate ?? DateTime(2000, 1, 1),
|
firstDate: widget.minDate ?? DateTime(2000, 1, 1),
|
||||||
lastDate: widget.maxDate ?? DateTime.now(),
|
lastDate: widget.maxDate ?? DateTime.now().add(const Duration(days: 365)),
|
||||||
);
|
);
|
||||||
widget.onChanged(newTime);
|
widget.onChanged(newTime);
|
||||||
},
|
},
|
||||||
|
@ -3,12 +3,12 @@ import 'package:diameter/object_box.dart';
|
|||||||
import 'package:diameter/screens/accuracy_detail.dart';
|
import 'package:diameter/screens/accuracy_detail.dart';
|
||||||
import 'package:diameter/screens/basal/basal_profile_detail.dart';
|
import 'package:diameter/screens/basal/basal_profile_detail.dart';
|
||||||
import 'package:diameter/screens/bolus/bolus_profile_detail.dart';
|
import 'package:diameter/screens/bolus/bolus_profile_detail.dart';
|
||||||
import 'package:diameter/screens/log/active_log_event_list.dart';
|
|
||||||
import 'package:diameter/screens/log/log.dart';
|
import 'package:diameter/screens/log/log.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_entry.dart';
|
import 'package:diameter/screens/log/log_entry/log_entry.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_event_detail.dart';
|
import 'package:diameter/screens/log/log_event/log_event_detail.dart';
|
||||||
import 'package:diameter/screens/log/log_event_type_detail.dart';
|
import 'package:diameter/screens/log/log_event/log_event_list.dart';
|
||||||
import 'package:diameter/screens/log/log_event_type_list.dart';
|
import 'package:diameter/screens/log/log_event/log_event_type_detail.dart';
|
||||||
|
import 'package:diameter/screens/log/log_event/log_event_type_list.dart';
|
||||||
import 'package:diameter/screens/meal/meal_category_detail.dart';
|
import 'package:diameter/screens/meal/meal_category_detail.dart';
|
||||||
import 'package:diameter/screens/meal/meal_category_list.dart';
|
import 'package:diameter/screens/meal/meal_category_list.dart';
|
||||||
import 'package:diameter/screens/meal/meal_detail.dart';
|
import 'package:diameter/screens/meal/meal_detail.dart';
|
||||||
@ -54,8 +54,8 @@ Future<void> main() async {
|
|||||||
Routes.logEntry: (context) => const LogEntryScreen(),
|
Routes.logEntry: (context) => const LogEntryScreen(),
|
||||||
Routes.logEvent: (context) => const LogEventDetailScreen(),
|
Routes.logEvent: (context) => const LogEventDetailScreen(),
|
||||||
Routes.logEventTypes: (context) => const LogEventTypeListScreen(),
|
Routes.logEventTypes: (context) => const LogEventTypeListScreen(),
|
||||||
Routes.logEventType: (context) => const LogEventTypeDetailScreen(),
|
Routes.logEventType: (context) => const EventTypeDetailScreen(),
|
||||||
Routes.activeEvents: (context) => const ActiveEventListScreen(),
|
Routes.events: (context) => const LogEventListScreen(),
|
||||||
Routes.accuracies: (context) => const AccuracyListScreen(),
|
Routes.accuracies: (context) => const AccuracyListScreen(),
|
||||||
Routes.accuracy: (context) => const AccuracyDetailScreen(),
|
Routes.accuracy: (context) => const AccuracyDetailScreen(),
|
||||||
Routes.meals: (context) => const MealListScreen(),
|
Routes.meals: (context) => const MealListScreen(),
|
||||||
|
@ -56,8 +56,16 @@ class LogBolus {
|
|||||||
return builder.build().find();
|
return builder.build().find();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double getTotalBolusForEntry(int id) {
|
||||||
|
QueryBuilder<LogBolus> builder = box.query(LogBolus_.deleted.equals(false));
|
||||||
|
builder.link(LogBolus_.logEntry, LogEntry_.id.equals(id));
|
||||||
|
return builder.build().property(LogBolus_.units).sum();
|
||||||
|
}
|
||||||
|
|
||||||
static bool glucoseBolusForEntryExists(int id) {
|
static bool glucoseBolusForEntryExists(int id) {
|
||||||
QueryBuilder<LogBolus> builder = box.query(LogBolus_.deleted.equals(false).and(LogBolus_.mgPerDlCorrection.notNull()));
|
QueryBuilder<LogBolus> builder = box.query(LogBolus_.deleted
|
||||||
|
.equals(false)
|
||||||
|
.and(LogBolus_.mgPerDlCorrection.notNull()));
|
||||||
builder.link(LogBolus_.logEntry, LogEntry_.id.equals(id));
|
builder.link(LogBolus_.logEntry, LogEntry_.id.equals(id));
|
||||||
return builder.build().find().isNotEmpty;
|
return builder.build().find().isNotEmpty;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import 'package:diameter/main.dart';
|
import 'package:diameter/main.dart';
|
||||||
import 'package:diameter/models/basal_profile.dart';
|
import 'package:diameter/models/basal_profile.dart';
|
||||||
import 'package:diameter/models/bolus_profile.dart';
|
import 'package:diameter/models/bolus_profile.dart';
|
||||||
import 'package:diameter/models/log_entry.dart';
|
|
||||||
import 'package:diameter/models/log_event_type.dart';
|
import 'package:diameter/models/log_event_type.dart';
|
||||||
import 'package:objectbox/objectbox.dart';
|
import 'package:objectbox/objectbox.dart';
|
||||||
import 'package:diameter/objectbox.g.dart' show LogEvent_, LogEntry_;
|
import 'package:diameter/objectbox.g.dart' show LogEvent_;
|
||||||
|
|
||||||
@Entity(uid: 4303325892753185970)
|
@Entity(uid: 4303325892753185970)
|
||||||
class LogEvent {
|
class LogEvent {
|
||||||
@ -22,8 +21,6 @@ class LogEvent {
|
|||||||
String? notes;
|
String? notes;
|
||||||
|
|
||||||
// relations
|
// relations
|
||||||
final logEntry = ToOne<LogEntry>();
|
|
||||||
final endLogEntry = ToOne<LogEntry>();
|
|
||||||
final eventType = ToOne<LogEventType>();
|
final eventType = ToOne<LogEventType>();
|
||||||
final bolusProfile = ToOne<BolusProfile>();
|
final bolusProfile = ToOne<BolusProfile>();
|
||||||
final basalProfile = ToOne<BasalProfile>();
|
final basalProfile = ToOne<BasalProfile>();
|
||||||
@ -73,18 +70,21 @@ class LogEvent {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<LogEvent> getAllForEntry(int id) {
|
static Map<DateTime, List<LogEvent>> getDailyEntryMap() {
|
||||||
QueryBuilder<LogEvent> builder = box.query(LogEvent_.deleted.equals(false))
|
Map<DateTime, List<LogEvent>> dateMap = <DateTime, List<LogEvent>>{};
|
||||||
..order(LogEvent_.time);
|
|
||||||
builder.link(LogEvent_.logEntry, LogEntry_.id.equals(id));
|
QueryBuilder<LogEvent> allByDate = box
|
||||||
return builder.build().find();
|
.query(LogEvent_.deleted.equals(false))
|
||||||
|
..order(LogEvent_.time, flags: Order.descending);
|
||||||
|
List<LogEvent> events = allByDate.build().find();
|
||||||
|
DateTime? date;
|
||||||
|
|
||||||
|
for (LogEvent event in events) {
|
||||||
|
date = DateTime.utc(event.time.year, event.time.month, event.time.day);
|
||||||
|
dateMap.putIfAbsent(date, () => <LogEvent>[]).add(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<LogEvent> getAllEndedByEntry(int id) {
|
return dateMap;
|
||||||
QueryBuilder<LogEvent> builder = box.query(LogEvent_.deleted.equals(false))
|
|
||||||
..order(LogEvent_.time);
|
|
||||||
builder.link(LogEvent_.endLogEntry, LogEntry_.id.equals(id));
|
|
||||||
return builder.build().find();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -59,6 +59,12 @@ class LogMeal {
|
|||||||
return builder.build().find();
|
return builder.build().find();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double getTotalCarbsForEntry(int id) {
|
||||||
|
QueryBuilder<LogMeal> builder = box.query(LogMeal_.deleted.equals(false));
|
||||||
|
builder.link(LogMeal_.logEntry, LogEntry_.id.equals(id));
|
||||||
|
return builder.build().property(LogMeal_.carbsPerPortion).sum();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return value;
|
return value;
|
||||||
|
@ -8,10 +8,10 @@ import 'package:diameter/screens/bolus/bolus_profile_detail.dart';
|
|||||||
import 'package:diameter/screens/bolus/bolus_profile_list.dart';
|
import 'package:diameter/screens/bolus/bolus_profile_list.dart';
|
||||||
import 'package:diameter/screens/log/log.dart';
|
import 'package:diameter/screens/log/log.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_entry.dart';
|
import 'package:diameter/screens/log/log_entry/log_entry.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_event_detail.dart';
|
import 'package:diameter/screens/log/log_event/log_event_detail.dart';
|
||||||
import 'package:diameter/screens/log/active_log_event_list.dart';
|
import 'package:diameter/screens/log/log_event/log_event_list.dart';
|
||||||
import 'package:diameter/screens/log/log_event_type_detail.dart';
|
import 'package:diameter/screens/log/log_event/log_event_type_detail.dart';
|
||||||
import 'package:diameter/screens/log/log_event_type_list.dart';
|
import 'package:diameter/screens/log/log_event/log_event_type_list.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_meal_detail.dart';
|
import 'package:diameter/screens/log/log_entry/log_meal_detail.dart';
|
||||||
import 'package:diameter/screens/meal/meal_category_detail.dart';
|
import 'package:diameter/screens/meal/meal_category_detail.dart';
|
||||||
import 'package:diameter/screens/meal/meal_category_list.dart';
|
import 'package:diameter/screens/meal/meal_category_list.dart';
|
||||||
@ -40,10 +40,10 @@ class Routes {
|
|||||||
static const String logEvent = LogEventDetailScreen.routeName;
|
static const String logEvent = LogEventDetailScreen.routeName;
|
||||||
static const String logMeal = LogMealDetailScreen.routeName;
|
static const String logMeal = LogMealDetailScreen.routeName;
|
||||||
static const List<String> logEntryRoutes = [logEntry, logEvent, logMeal];
|
static const List<String> logEntryRoutes = [logEntry, logEvent, logMeal];
|
||||||
static const String logEventType = LogEventTypeDetailScreen.routeName;
|
static const String logEventType = EventTypeDetailScreen.routeName;
|
||||||
static const String logEventTypes = LogEventTypeListScreen.routeName;
|
static const String logEventTypes = LogEventTypeListScreen.routeName;
|
||||||
static const List<String> logEventTypeRoutes = [logEventType, logEventTypes];
|
static const List<String> logEventTypeRoutes = [logEventType, logEventTypes];
|
||||||
static const String activeEvents = ActiveEventListScreen.routeName;
|
static const String events = LogEventListScreen.routeName;
|
||||||
|
|
||||||
static const String meal = MealDetailScreen.routeName;
|
static const String meal = MealDetailScreen.routeName;
|
||||||
static const String meals = MealListScreen.routeName;
|
static const String meals = MealListScreen.routeName;
|
||||||
@ -108,12 +108,12 @@ class _NavigationState extends State<Navigation> {
|
|||||||
selected: Routes.logEntryRoutes.contains(widget.currentLocation),
|
selected: Routes.logEntryRoutes.contains(widget.currentLocation),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Active Events'),
|
title: const Text('Log Events'),
|
||||||
leading: const Icon(Icons.event),
|
leading: const Icon(Icons.event),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
selectDestination(Routes.activeEvents);
|
selectDestination(Routes.events);
|
||||||
},
|
},
|
||||||
selected: widget.currentLocation == Routes.activeEvents,
|
selected: widget.currentLocation == Routes.events,
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Meals'),
|
title: const Text('Meals'),
|
||||||
|
@ -240,22 +240,6 @@
|
|||||||
"name": "notes",
|
"name": "notes",
|
||||||
"type": 9
|
"type": 9
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "6:7838546213550447420",
|
|
||||||
"name": "logEntryId",
|
|
||||||
"type": 11,
|
|
||||||
"flags": 520,
|
|
||||||
"indexId": "3:3670661188280692002",
|
|
||||||
"relationTarget": "LogEntry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "7:8031421171668506924",
|
|
||||||
"name": "endLogEntryId",
|
|
||||||
"type": 11,
|
|
||||||
"flags": 520,
|
|
||||||
"indexId": "4:7379712902406481832",
|
|
||||||
"relationTarget": "LogEntry"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "8:2514297323717317184",
|
"id": "8:2514297323717317184",
|
||||||
"name": "eventTypeId",
|
"name": "eventTypeId",
|
||||||
@ -818,7 +802,10 @@
|
|||||||
"retiredEntityUids": [
|
"retiredEntityUids": [
|
||||||
3095978685310268382
|
3095978685310268382
|
||||||
],
|
],
|
||||||
"retiredIndexUids": [],
|
"retiredIndexUids": [
|
||||||
|
3670661188280692002,
|
||||||
|
7379712902406481832
|
||||||
|
],
|
||||||
"retiredPropertyUids": [
|
"retiredPropertyUids": [
|
||||||
3455702077061719523,
|
3455702077061719523,
|
||||||
1048198814030724077,
|
1048198814030724077,
|
||||||
@ -832,7 +819,9 @@
|
|||||||
1568597071506264632,
|
1568597071506264632,
|
||||||
8795268969829293398,
|
8795268969829293398,
|
||||||
3247926313599127440,
|
3247926313599127440,
|
||||||
8789440370359282572
|
8789440370359282572,
|
||||||
|
7838546213550447420,
|
||||||
|
8031421171668506924
|
||||||
],
|
],
|
||||||
"retiredRelationUids": [],
|
"retiredRelationUids": [],
|
||||||
"version": 1
|
"version": 1
|
||||||
|
@ -262,20 +262,6 @@ final _entities = <ModelEntity>[
|
|||||||
name: 'notes',
|
name: 'notes',
|
||||||
type: 9,
|
type: 9,
|
||||||
flags: 0),
|
flags: 0),
|
||||||
ModelProperty(
|
|
||||||
id: const IdUid(6, 7838546213550447420),
|
|
||||||
name: 'logEntryId',
|
|
||||||
type: 11,
|
|
||||||
flags: 520,
|
|
||||||
indexId: const IdUid(3, 3670661188280692002),
|
|
||||||
relationTarget: 'LogEntry'),
|
|
||||||
ModelProperty(
|
|
||||||
id: const IdUid(7, 8031421171668506924),
|
|
||||||
name: 'endLogEntryId',
|
|
||||||
type: 11,
|
|
||||||
flags: 520,
|
|
||||||
indexId: const IdUid(4, 7379712902406481832),
|
|
||||||
relationTarget: 'LogEntry'),
|
|
||||||
ModelProperty(
|
ModelProperty(
|
||||||
id: const IdUid(8, 2514297323717317184),
|
id: const IdUid(8, 2514297323717317184),
|
||||||
name: 'eventTypeId',
|
name: 'eventTypeId',
|
||||||
@ -831,7 +817,7 @@ ModelDefinition getObjectBoxModel() {
|
|||||||
lastRelationId: const IdUid(0, 0),
|
lastRelationId: const IdUid(0, 0),
|
||||||
lastSequenceId: const IdUid(0, 0),
|
lastSequenceId: const IdUid(0, 0),
|
||||||
retiredEntityUids: const [3095978685310268382],
|
retiredEntityUids: const [3095978685310268382],
|
||||||
retiredIndexUids: const [],
|
retiredIndexUids: const [3670661188280692002, 7379712902406481832],
|
||||||
retiredPropertyUids: const [
|
retiredPropertyUids: const [
|
||||||
3455702077061719523,
|
3455702077061719523,
|
||||||
1048198814030724077,
|
1048198814030724077,
|
||||||
@ -845,7 +831,9 @@ ModelDefinition getObjectBoxModel() {
|
|||||||
1568597071506264632,
|
1568597071506264632,
|
||||||
8795268969829293398,
|
8795268969829293398,
|
||||||
3247926313599127440,
|
3247926313599127440,
|
||||||
8789440370359282572
|
8789440370359282572,
|
||||||
|
7838546213550447420,
|
||||||
|
8031421171668506924
|
||||||
],
|
],
|
||||||
retiredRelationUids: const [],
|
retiredRelationUids: const [],
|
||||||
modelVersion: 5,
|
modelVersion: 5,
|
||||||
@ -1056,13 +1044,8 @@ ModelDefinition getObjectBoxModel() {
|
|||||||
}),
|
}),
|
||||||
LogEvent: EntityDefinition<LogEvent>(
|
LogEvent: EntityDefinition<LogEvent>(
|
||||||
model: _entities[5],
|
model: _entities[5],
|
||||||
toOneRelations: (LogEvent object) => [
|
toOneRelations: (LogEvent object) =>
|
||||||
object.logEntry,
|
[object.eventType, object.bolusProfile, object.basalProfile],
|
||||||
object.endLogEntry,
|
|
||||||
object.eventType,
|
|
||||||
object.bolusProfile,
|
|
||||||
object.basalProfile
|
|
||||||
],
|
|
||||||
toManyRelations: (LogEvent object) => {},
|
toManyRelations: (LogEvent object) => {},
|
||||||
getId: (LogEvent object) => object.id,
|
getId: (LogEvent object) => object.id,
|
||||||
setId: (LogEvent object, int id) {
|
setId: (LogEvent object, int id) {
|
||||||
@ -1077,8 +1060,6 @@ ModelDefinition getObjectBoxModel() {
|
|||||||
fbb.addInt64(2, object.endTime?.millisecondsSinceEpoch);
|
fbb.addInt64(2, object.endTime?.millisecondsSinceEpoch);
|
||||||
fbb.addBool(3, object.hasEndTime);
|
fbb.addBool(3, object.hasEndTime);
|
||||||
fbb.addOffset(4, notesOffset);
|
fbb.addOffset(4, notesOffset);
|
||||||
fbb.addInt64(5, object.logEntry.targetId);
|
|
||||||
fbb.addInt64(6, object.endLogEntry.targetId);
|
|
||||||
fbb.addInt64(7, object.eventType.targetId);
|
fbb.addInt64(7, object.eventType.targetId);
|
||||||
fbb.addBool(8, object.deleted);
|
fbb.addBool(8, object.deleted);
|
||||||
fbb.addInt64(9, object.bolusProfile.targetId);
|
fbb.addInt64(9, object.bolusProfile.targetId);
|
||||||
@ -1107,12 +1088,6 @@ ModelDefinition getObjectBoxModel() {
|
|||||||
.vTableGetNullable(buffer, rootOffset, 26),
|
.vTableGetNullable(buffer, rootOffset, 26),
|
||||||
notes: const fb.StringReader()
|
notes: const fb.StringReader()
|
||||||
.vTableGetNullable(buffer, rootOffset, 12));
|
.vTableGetNullable(buffer, rootOffset, 12));
|
||||||
object.logEntry.targetId =
|
|
||||||
const fb.Int64Reader().vTableGet(buffer, rootOffset, 14, 0);
|
|
||||||
object.logEntry.attach(store);
|
|
||||||
object.endLogEntry.targetId =
|
|
||||||
const fb.Int64Reader().vTableGet(buffer, rootOffset, 16, 0);
|
|
||||||
object.endLogEntry.attach(store);
|
|
||||||
object.eventType.targetId =
|
object.eventType.targetId =
|
||||||
const fb.Int64Reader().vTableGet(buffer, rootOffset, 18, 0);
|
const fb.Int64Reader().vTableGet(buffer, rootOffset, 18, 0);
|
||||||
object.eventType.attach(store);
|
object.eventType.attach(store);
|
||||||
@ -1731,33 +1706,25 @@ class LogEvent_ {
|
|||||||
static final notes =
|
static final notes =
|
||||||
QueryStringProperty<LogEvent>(_entities[5].properties[4]);
|
QueryStringProperty<LogEvent>(_entities[5].properties[4]);
|
||||||
|
|
||||||
/// see [LogEvent.logEntry]
|
|
||||||
static final logEntry =
|
|
||||||
QueryRelationToOne<LogEvent, LogEntry>(_entities[5].properties[5]);
|
|
||||||
|
|
||||||
/// see [LogEvent.endLogEntry]
|
|
||||||
static final endLogEntry =
|
|
||||||
QueryRelationToOne<LogEvent, LogEntry>(_entities[5].properties[6]);
|
|
||||||
|
|
||||||
/// see [LogEvent.eventType]
|
/// see [LogEvent.eventType]
|
||||||
static final eventType =
|
static final eventType =
|
||||||
QueryRelationToOne<LogEvent, LogEventType>(_entities[5].properties[7]);
|
QueryRelationToOne<LogEvent, LogEventType>(_entities[5].properties[5]);
|
||||||
|
|
||||||
/// see [LogEvent.deleted]
|
/// see [LogEvent.deleted]
|
||||||
static final deleted =
|
static final deleted =
|
||||||
QueryBooleanProperty<LogEvent>(_entities[5].properties[8]);
|
QueryBooleanProperty<LogEvent>(_entities[5].properties[6]);
|
||||||
|
|
||||||
/// see [LogEvent.bolusProfile]
|
/// see [LogEvent.bolusProfile]
|
||||||
static final bolusProfile =
|
static final bolusProfile =
|
||||||
QueryRelationToOne<LogEvent, BolusProfile>(_entities[5].properties[9]);
|
QueryRelationToOne<LogEvent, BolusProfile>(_entities[5].properties[7]);
|
||||||
|
|
||||||
/// see [LogEvent.basalProfile]
|
/// see [LogEvent.basalProfile]
|
||||||
static final basalProfile =
|
static final basalProfile =
|
||||||
QueryRelationToOne<LogEvent, BasalProfile>(_entities[5].properties[10]);
|
QueryRelationToOne<LogEvent, BasalProfile>(_entities[5].properties[8]);
|
||||||
|
|
||||||
/// see [LogEvent.reminderDuration]
|
/// see [LogEvent.reminderDuration]
|
||||||
static final reminderDuration =
|
static final reminderDuration =
|
||||||
QueryIntegerProperty<LogEvent>(_entities[5].properties[11]);
|
QueryIntegerProperty<LogEvent>(_entities[5].properties[9]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [LogEventType] entity fields to define ObjectBox queries.
|
/// [LogEventType] entity fields to define ObjectBox queries.
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
import 'package:diameter/models/log_event.dart';
|
|
||||||
import 'package:diameter/screens/log/log_entry/log_event_detail.dart';
|
|
||||||
import 'package:diameter/screens/log/log_entry/log_event_list.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:diameter/navigation.dart';
|
|
||||||
|
|
||||||
class ActiveEventListScreen extends StatefulWidget {
|
|
||||||
static const String routeName = '/active-log-events';
|
|
||||||
const ActiveEventListScreen({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_ActiveEventListScreenState createState() => _ActiveEventListScreenState();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class _ActiveEventListScreenState extends State<ActiveEventListScreen> {
|
|
||||||
List<LogEvent> _activeEvents = [];
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
void reload({String? message}) {
|
|
||||||
setState(() {
|
|
||||||
_activeEvents = LogEvent.getAllActiveForTime(DateTime.now());
|
|
||||||
});
|
|
||||||
|
|
||||||
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 const LogEventDetailScreen();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
).then((message) => reload(message: message));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: const Text('Active Events'),
|
|
||||||
actions: <Widget>[
|
|
||||||
IconButton(onPressed: reload, icon: const Icon(Icons.refresh))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
drawer:
|
|
||||||
const Navigation(currentLocation: ActiveEventListScreen.routeName),
|
|
||||||
body: LogEventListScreen(activeEvents: _activeEvents),
|
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: handleAddNewEvent,
|
|
||||||
child: const Icon(Icons.add),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,11 @@
|
|||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/config.dart';
|
||||||
|
import 'package:diameter/models/log_bolus.dart';
|
||||||
import 'package:diameter/models/log_entry.dart';
|
import 'package:diameter/models/log_entry.dart';
|
||||||
|
import 'package:diameter/models/log_meal.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_entry.dart';
|
import 'package:diameter/screens/log/log_entry/log_entry.dart';
|
||||||
|
import 'package:diameter/settings.dart';
|
||||||
import 'package:diameter/utils/date_time_utils.dart';
|
import 'package:diameter/utils/date_time_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@ -63,10 +66,7 @@ class _LogScreenState extends State<LogScreen> {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Log Entries'),
|
title: const Text('Log Entries'),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
IconButton(
|
IconButton(onPressed: reload, icon: const Icon(Icons.refresh)),
|
||||||
onPressed: reload,
|
|
||||||
icon: const Icon(Icons.refresh)
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
drawer: const Navigation(currentLocation: LogScreen.routeName),
|
drawer: const Navigation(currentLocation: LogScreen.routeName),
|
||||||
@ -74,13 +74,15 @@ class _LogScreenState extends State<LogScreen> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _logEntryDailyMap.isNotEmpty ? SingleChildScrollView(
|
child: _logEntryDailyMap.isNotEmpty
|
||||||
|
? SingleChildScrollView(
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(10.0),
|
||||||
itemCount: _logEntryDailyMap.length,
|
itemCount: _logEntryDailyMap.length,
|
||||||
itemBuilder: (context, dateIndex) {
|
itemBuilder: (context, dateIndex) {
|
||||||
List<DateTime> dateList = _logEntryDailyMap.keys.toList();
|
List<DateTime> dateList =
|
||||||
|
_logEntryDailyMap.keys.toList();
|
||||||
final date = dateList[dateIndex];
|
final date = dateList[dateIndex];
|
||||||
final entryList = _logEntryDailyMap[date];
|
final entryList = _logEntryDailyMap[date];
|
||||||
return ListBody(
|
return ListBody(
|
||||||
@ -92,6 +94,12 @@ class _LogScreenState extends State<LogScreen> {
|
|||||||
itemCount: entryList.length,
|
itemCount: entryList.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final logEntry = entryList[index];
|
final logEntry = entryList[index];
|
||||||
|
double bolus =
|
||||||
|
LogBolus.getTotalBolusForEntry(
|
||||||
|
logEntry.id);
|
||||||
|
double carbs =
|
||||||
|
LogMeal.getTotalCarbsForEntry(
|
||||||
|
logEntry.id);
|
||||||
return ListTile(
|
return ListTile(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
@ -101,48 +109,134 @@ class _LogScreenState extends State<LogScreen> {
|
|||||||
LogEntryScreen(
|
LogEntryScreen(
|
||||||
id: logEntry.id),
|
id: logEntry.id),
|
||||||
),
|
),
|
||||||
).then((message) => reload(
|
).then((message) =>
|
||||||
message: message));
|
reload(message: message));
|
||||||
},
|
},
|
||||||
title: Text(
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
DateTimeUtils.displayTime(
|
DateTimeUtils.displayTime(
|
||||||
logEntry.time)),
|
logEntry.time),
|
||||||
// ignore: todo
|
),
|
||||||
// TODO: add more data (event, glucose color...)
|
),
|
||||||
subtitle: Text(logEntry
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
children: logEntry
|
||||||
.mgPerDl !=
|
.mgPerDl !=
|
||||||
null
|
null &&
|
||||||
? '${logEntry.mgPerDl.toString()} mg/dl'
|
(glucoseMeasurement == GlucoseMeasurement.mgPerDl ||
|
||||||
: ''),
|
glucoseDisplayMode ==
|
||||||
|
GlucoseDisplayMode
|
||||||
|
.both ||
|
||||||
|
glucoseDisplayMode ==
|
||||||
|
GlucoseDisplayMode
|
||||||
|
.bothForList)
|
||||||
|
? [
|
||||||
|
Text(logEntry
|
||||||
|
.mgPerDl
|
||||||
|
.toString()),
|
||||||
|
const Text(
|
||||||
|
'mg/dl',
|
||||||
|
textScaleFactor:
|
||||||
|
0.75,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
: [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
children: logEntry
|
||||||
|
.mmolPerL !=
|
||||||
|
null &&
|
||||||
|
(glucoseMeasurement == GlucoseMeasurement.mmolPerL ||
|
||||||
|
glucoseDisplayMode ==
|
||||||
|
GlucoseDisplayMode
|
||||||
|
.both ||
|
||||||
|
glucoseDisplayMode ==
|
||||||
|
GlucoseDisplayMode
|
||||||
|
.bothForList)
|
||||||
|
? [
|
||||||
|
Text(logEntry
|
||||||
|
.mmolPerL
|
||||||
|
.toString()),
|
||||||
|
const Text(
|
||||||
|
'mmol/l',
|
||||||
|
textScaleFactor:
|
||||||
|
0.75,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
: [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
children: (bolus > 0)
|
||||||
|
? [
|
||||||
|
Text(bolus
|
||||||
|
.toStringAsPrecision(
|
||||||
|
3)),
|
||||||
|
const Text('U',
|
||||||
|
textScaleFactor:
|
||||||
|
0.75),
|
||||||
|
]
|
||||||
|
: [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
children: (carbs > 0)
|
||||||
|
? [
|
||||||
|
Text(carbs
|
||||||
|
.toStringAsPrecision(
|
||||||
|
3)),
|
||||||
|
Text(
|
||||||
|
nutritionMeasurement ==
|
||||||
|
NutritionMeasurement
|
||||||
|
.grams
|
||||||
|
? 'g carbs'
|
||||||
|
: nutritionMeasurement ==
|
||||||
|
NutritionMeasurement
|
||||||
|
.ounces
|
||||||
|
? 'oz carbs'
|
||||||
|
: '',
|
||||||
|
textScaleFactor:
|
||||||
|
0.75),
|
||||||
|
]
|
||||||
|
: [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
trailing: Row(
|
trailing: Row(
|
||||||
mainAxisSize:
|
mainAxisSize: MainAxisSize.min,
|
||||||
MainAxisSize.min,
|
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
handleDeleteAction(
|
handleDeleteAction(logEntry),
|
||||||
logEntry),
|
icon: const Icon(Icons.delete,
|
||||||
icon: const Icon(
|
|
||||||
Icons.delete,
|
|
||||||
color: Colors.blue),
|
color: Colors.blue),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
})
|
||||||
) : Container(),
|
: Container(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
) : const Center(
|
)
|
||||||
|
: const Center(
|
||||||
child: Text('You have not created any Log Entries yet!'),
|
child: Text('You have not created any Log Entries yet!'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
// ignore: todo
|
|
||||||
// TODO: add button for active events
|
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
|
@ -4,13 +4,10 @@ import 'package:diameter/components/forms.dart';
|
|||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/config.dart';
|
||||||
import 'package:diameter/models/log_bolus.dart';
|
import 'package:diameter/models/log_bolus.dart';
|
||||||
import 'package:diameter/models/log_entry.dart';
|
import 'package:diameter/models/log_entry.dart';
|
||||||
import 'package:diameter/models/log_event.dart';
|
|
||||||
import 'package:diameter/models/log_meal.dart';
|
import 'package:diameter/models/log_meal.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_bolus_detail.dart';
|
import 'package:diameter/screens/log/log_entry/log_bolus_detail.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_bolus_list.dart';
|
import 'package:diameter/screens/log/log_entry/log_bolus_list.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_event_list.dart';
|
|
||||||
import 'package:diameter/screens/log/log_entry/log_event_detail.dart';
|
|
||||||
import 'package:diameter/screens/log/log_entry/log_meal_detail.dart';
|
import 'package:diameter/screens/log/log_entry/log_meal_detail.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_meal_list.dart';
|
import 'package:diameter/screens/log/log_entry/log_meal_list.dart';
|
||||||
import 'package:diameter/settings.dart';
|
import 'package:diameter/settings.dart';
|
||||||
@ -31,15 +28,13 @@ class LogEntryScreen extends StatefulWidget {
|
|||||||
class _LogEntryScreenState extends State<LogEntryScreen> {
|
class _LogEntryScreenState extends State<LogEntryScreen> {
|
||||||
LogEntry? _logEntry;
|
LogEntry? _logEntry;
|
||||||
List<LogMeal> _logMeals = [];
|
List<LogMeal> _logMeals = [];
|
||||||
List<LogEvent> _logEvents = [];
|
|
||||||
List<LogEvent> _activeEvents = [];
|
|
||||||
List<LogBolus> _logBoli = [];
|
List<LogBolus> _logBoli = [];
|
||||||
bool _isNew = true;
|
bool _isNew = true;
|
||||||
bool _isSaving = false;
|
bool _isSaving = false;
|
||||||
|
|
||||||
final GlobalKey<FormState> logEntryForm = GlobalKey<FormState>();
|
final GlobalKey<FormState> logEntryForm = GlobalKey<FormState>();
|
||||||
|
|
||||||
DateTime _time = DateTime.now();
|
late DateTime _time;
|
||||||
|
|
||||||
final _timeController = TextEditingController(text: '');
|
final _timeController = TextEditingController(text: '');
|
||||||
final _dateController = TextEditingController(text: '');
|
final _dateController = TextEditingController(text: '');
|
||||||
@ -49,7 +44,6 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
|||||||
|
|
||||||
late FloatingActionButton addMealButton;
|
late FloatingActionButton addMealButton;
|
||||||
late FloatingActionButton addBolusButton;
|
late FloatingActionButton addBolusButton;
|
||||||
late FloatingActionButton addEventButton;
|
|
||||||
late IconButton refreshButton;
|
late IconButton refreshButton;
|
||||||
late IconButton closeButton;
|
late IconButton closeButton;
|
||||||
late DetailBottomRow detailBottomRow;
|
late DetailBottomRow detailBottomRow;
|
||||||
@ -74,11 +68,6 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
|||||||
child: const Icon(Icons.add),
|
child: const Icon(Icons.add),
|
||||||
);
|
);
|
||||||
|
|
||||||
addEventButton = FloatingActionButton(
|
|
||||||
onPressed: handleAddNewEvent,
|
|
||||||
child: const Icon(Icons.add),
|
|
||||||
);
|
|
||||||
|
|
||||||
refreshButton = IconButton(
|
refreshButton = IconButton(
|
||||||
icon: const Icon(Icons.refresh),
|
icon: const Icon(Icons.refresh),
|
||||||
onPressed: reload,
|
onPressed: reload,
|
||||||
@ -103,6 +92,8 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
|||||||
_mgPerDlController.text = (_logEntry!.mgPerDl ?? '').toString();
|
_mgPerDlController.text = (_logEntry!.mgPerDl ?? '').toString();
|
||||||
_mmolPerLController.text = (_logEntry!.mmolPerL ?? '').toString();
|
_mmolPerLController.text = (_logEntry!.mmolPerL ?? '').toString();
|
||||||
_notesController.text = _logEntry!.notes ?? '';
|
_notesController.text = _logEntry!.notes ?? '';
|
||||||
|
} else {
|
||||||
|
_time = DateTime.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTime();
|
updateTime();
|
||||||
@ -113,8 +104,6 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_logEntry = LogEntry.get(widget.id);
|
_logEntry = LogEntry.get(widget.id);
|
||||||
_logMeals = LogMeal.getAllForEntry(widget.id);
|
_logMeals = LogMeal.getAllForEntry(widget.id);
|
||||||
_logEvents = LogEvent.getAllForEntry(widget.id);
|
|
||||||
_activeEvents = LogEvent.getAllActiveForTime(_logEntry?.time).where((event) => !_logEvents.any((logEvent) => logEvent.id == event.id)).toList();
|
|
||||||
_logBoli = LogBolus.getAllForEntry(widget.id);
|
_logBoli = LogBolus.getAllForEntry(widget.id);
|
||||||
});
|
});
|
||||||
_isNew = _logEntry == null;
|
_isNew = _logEntry == null;
|
||||||
@ -230,17 +219,6 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
|||||||
).then((message) => reload(message: message));
|
).then((message) => reload(message: message));
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleAddNewEvent() async {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return LogEventDetailScreen(logEntryId: _logEntry!.id);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
).then((message) => reload(message: message));
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderTabButtons(index) {
|
void renderTabButtons(index) {
|
||||||
if (_logEntry != null) {
|
if (_logEntry != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -255,11 +233,6 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
|||||||
appBarActions = [refreshButton, closeButton];
|
appBarActions = [refreshButton, closeButton];
|
||||||
bottomNav = null;
|
bottomNav = null;
|
||||||
break;
|
break;
|
||||||
case 3:
|
|
||||||
actionButton = addEventButton;
|
|
||||||
appBarActions = [refreshButton, closeButton];
|
|
||||||
bottomNav = null;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
actionButton = null;
|
actionButton = null;
|
||||||
appBarActions = [closeButton];
|
appBarActions = [closeButton];
|
||||||
@ -272,7 +245,7 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DefaultTabController(
|
return DefaultTabController(
|
||||||
length: _isNew ? 1 : 4,
|
length: _isNew ? 1 : 3,
|
||||||
child: Builder(builder: (BuildContext context) {
|
child: Builder(builder: (BuildContext context) {
|
||||||
final TabController tabController = DefaultTabController.of(context)!;
|
final TabController tabController = DefaultTabController.of(context)!;
|
||||||
tabController.addListener(() {
|
tabController.addListener(() {
|
||||||
@ -442,11 +415,6 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
|||||||
logEntry: _logEntry!, logMeals: _logMeals, reload: reload));
|
logEntry: _logEntry!, logMeals: _logMeals, reload: reload));
|
||||||
tabs.add(LogBolusListScreen(
|
tabs.add(LogBolusListScreen(
|
||||||
logEntry: _logEntry!, logBoli: _logBoli, reload: reload));
|
logEntry: _logEntry!, logBoli: _logBoli, reload: reload));
|
||||||
tabs.add(LogEventListScreen(
|
|
||||||
logEntry: _logEntry!,
|
|
||||||
logEvents: _logEvents,
|
|
||||||
activeEvents: _activeEvents,
|
|
||||||
reload: reload));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -459,7 +427,6 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
|||||||
Tab(text: 'GENERAL'),
|
Tab(text: 'GENERAL'),
|
||||||
Tab(text: 'MEALS'),
|
Tab(text: 'MEALS'),
|
||||||
Tab(text: 'BOLI'),
|
Tab(text: 'BOLI'),
|
||||||
Tab(text: 'EVENTS'),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: appBarActions,
|
actions: appBarActions,
|
||||||
|
@ -1,228 +0,0 @@
|
|||||||
import 'package:diameter/components/detail.dart';
|
|
||||||
import 'package:diameter/components/dialogs.dart';
|
|
||||||
import 'package:diameter/components/dropdown.dart';
|
|
||||||
import 'package:diameter/components/forms.dart';
|
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/basal_profile.dart';
|
|
||||||
import 'package:diameter/models/bolus_profile.dart';
|
|
||||||
import 'package:diameter/models/log_entry.dart';
|
|
||||||
import 'package:diameter/models/log_event.dart';
|
|
||||||
import 'package:diameter/models/log_event_type.dart';
|
|
||||||
import 'package:diameter/navigation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class LogEventDetailScreen extends StatefulWidget {
|
|
||||||
static const String routeName = '/log-event';
|
|
||||||
|
|
||||||
final int logEntryId;
|
|
||||||
final int endLogEntryId;
|
|
||||||
final int id;
|
|
||||||
|
|
||||||
const LogEventDetailScreen(
|
|
||||||
{Key? key, this.logEntryId = 0, this.endLogEntryId = 0, this.id = 0})
|
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_LogEventDetailScreenState createState() => _LogEventDetailScreenState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _LogEventDetailScreenState extends State<LogEventDetailScreen> {
|
|
||||||
LogEvent? _logEvent;
|
|
||||||
bool _isNew = true;
|
|
||||||
bool _isSaving = false;
|
|
||||||
|
|
||||||
List<BolusProfile> _bolusProfiles = [];
|
|
||||||
List<BasalProfile> _basalProfiles = [];
|
|
||||||
|
|
||||||
final GlobalKey<FormState> _logEventForm = GlobalKey<FormState>();
|
|
||||||
|
|
||||||
final _reminderDurationController = TextEditingController(text: '');
|
|
||||||
final _notesController = TextEditingController(text: '');
|
|
||||||
LogEventType? _eventType;
|
|
||||||
bool _hasEndTime = false;
|
|
||||||
BolusProfile? _bolusProfile;
|
|
||||||
BasalProfile? _basalProfile;
|
|
||||||
|
|
||||||
List<LogEventType> _logEventTypes = [];
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
reload();
|
|
||||||
|
|
||||||
_bolusProfiles = BolusProfile.getAll();
|
|
||||||
_basalProfiles = BasalProfile.getAll();
|
|
||||||
|
|
||||||
if (_logEvent != null) {
|
|
||||||
_reminderDurationController.text =
|
|
||||||
(_logEvent!.reminderDuration ?? '').toString();
|
|
||||||
_hasEndTime = _logEvent!.hasEndTime;
|
|
||||||
_notesController.text = _logEvent!.notes ?? '';
|
|
||||||
_eventType = _logEvent!.eventType.target;
|
|
||||||
_basalProfile = _logEvent!.basalProfile.target;
|
|
||||||
_bolusProfile = _logEvent!.bolusProfile.target;
|
|
||||||
}
|
|
||||||
|
|
||||||
_logEventTypes = LogEventType.getAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
void reload() {
|
|
||||||
if (widget.id != 0) {
|
|
||||||
setState(() {
|
|
||||||
_logEvent = LogEvent.get(widget.id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_isNew = _logEvent == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onSelectEventType(LogEventType eventType) {
|
|
||||||
setState(() {
|
|
||||||
_eventType = eventType;
|
|
||||||
_hasEndTime = eventType.hasEndTime;
|
|
||||||
if (eventType.basalProfile.target != null) {
|
|
||||||
_basalProfile = eventType.basalProfile.target;
|
|
||||||
}
|
|
||||||
if (eventType.bolusProfile.target != null) {
|
|
||||||
_bolusProfile = eventType.bolusProfile.target;
|
|
||||||
}
|
|
||||||
if (eventType.defaultReminderDuration != null) {
|
|
||||||
_reminderDurationController.text =
|
|
||||||
eventType.defaultReminderDuration.toString();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleSaveAction() async {
|
|
||||||
setState(() {
|
|
||||||
_isSaving = true;
|
|
||||||
});
|
|
||||||
if (_logEventForm.currentState!.validate()) {
|
|
||||||
LogEvent event = LogEvent(
|
|
||||||
id: widget.id,
|
|
||||||
time: LogEntry.get(widget.logEntryId)?.time ?? DateTime.now(),
|
|
||||||
hasEndTime: _hasEndTime,
|
|
||||||
reminderDuration: int.tryParse(_reminderDurationController.text),
|
|
||||||
notes: _notesController.text,
|
|
||||||
);
|
|
||||||
if (widget.logEntryId != 0) {
|
|
||||||
event.logEntry.targetId = widget.logEntryId;
|
|
||||||
} else {
|
|
||||||
event.logEntry.target = LogEntry(time: DateTime.now());
|
|
||||||
}
|
|
||||||
event.eventType.target = _eventType;
|
|
||||||
event.basalProfile.target = _basalProfile;
|
|
||||||
event.bolusProfile.target = _bolusProfile;
|
|
||||||
LogEvent.put(event);
|
|
||||||
Navigator.pop(context, '${_isNew ? 'New' : ''} Event Saved');
|
|
||||||
}
|
|
||||||
setState(() {
|
|
||||||
_isSaving = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleCancelAction() {
|
|
||||||
if (showConfirmationDialogOnCancel &&
|
|
||||||
((_isNew &&
|
|
||||||
(_notesController.text != '' ||
|
|
||||||
_eventType != null ||
|
|
||||||
_hasEndTime)) ||
|
|
||||||
(!_isNew &&
|
|
||||||
(_notesController.text != (_logEvent!.notes ?? '') ||
|
|
||||||
_eventType != _logEvent!.eventType.target ||
|
|
||||||
_hasEndTime != _logEvent!.hasEndTime)))) {
|
|
||||||
Dialogs.showCancelConfirmationDialog(
|
|
||||||
context: context,
|
|
||||||
isNew: _isNew,
|
|
||||||
onSave: handleSaveAction,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
Navigator.pop(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text(_isNew ? 'New Event' : 'Edit Event'),
|
|
||||||
),
|
|
||||||
drawer: const Navigation(currentLocation: LogEventDetailScreen.routeName),
|
|
||||||
body: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: <Widget>[
|
|
||||||
FormWrapper(
|
|
||||||
formState: _logEventForm,
|
|
||||||
fields: [
|
|
||||||
AutoCompleteDropdownButton<LogEventType>(
|
|
||||||
selectedItem: _eventType,
|
|
||||||
label: 'Event Type',
|
|
||||||
items: _logEventTypes,
|
|
||||||
onChanged: (value) {
|
|
||||||
if (value != null) {
|
|
||||||
onSelectEventType(value);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
BooleanFormField(
|
|
||||||
value: _hasEndTime,
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
_hasEndTime = value;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
label: 'has end time',
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
children: _hasEndTime ? [
|
|
||||||
TextFormField(
|
|
||||||
controller: _reminderDurationController,
|
|
||||||
keyboardType: const TextInputType.numberWithOptions(),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'Default Reminder Duration',
|
|
||||||
suffixText: ' min',
|
|
||||||
enabled: _hasEndTime,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
AutoCompleteDropdownButton<BolusProfile>(
|
|
||||||
selectedItem: _bolusProfile,
|
|
||||||
label: 'Bolus Profile',
|
|
||||||
items: _bolusProfiles,
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
_bolusProfile = value;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
AutoCompleteDropdownButton<BasalProfile>(
|
|
||||||
selectedItem: _basalProfile,
|
|
||||||
label: 'Basal Profile',
|
|
||||||
items: _basalProfiles,
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
_basalProfile = value;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
)
|
|
||||||
] : []),
|
|
||||||
TextFormField(
|
|
||||||
controller: _notesController,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Notes',
|
|
||||||
alignLabelWithHint: true,
|
|
||||||
),
|
|
||||||
keyboardType: TextInputType.multiline,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
bottomNavigationBar: DetailBottomRow(
|
|
||||||
onCancel: handleCancelAction,
|
|
||||||
onSave: _isSaving ? null : handleSaveAction,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
366
lib/screens/log/log_event/log_event_detail.dart
Normal file
366
lib/screens/log/log_event/log_event_detail.dart
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
import 'package:diameter/components/detail.dart';
|
||||||
|
import 'package:diameter/components/dialogs.dart';
|
||||||
|
import 'package:diameter/components/dropdown.dart';
|
||||||
|
import 'package:diameter/components/forms.dart';
|
||||||
|
import 'package:diameter/config.dart';
|
||||||
|
import 'package:diameter/models/basal_profile.dart';
|
||||||
|
import 'package:diameter/models/bolus_profile.dart';
|
||||||
|
import 'package:diameter/models/log_event.dart';
|
||||||
|
import 'package:diameter/models/log_event_type.dart';
|
||||||
|
import 'package:diameter/navigation.dart';
|
||||||
|
import 'package:diameter/utils/date_time_utils.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class LogEventDetailScreen extends StatefulWidget {
|
||||||
|
static const String routeName = '/log-event';
|
||||||
|
|
||||||
|
final int logEntryId;
|
||||||
|
final int endLogEntryId;
|
||||||
|
final int id;
|
||||||
|
|
||||||
|
const LogEventDetailScreen(
|
||||||
|
{Key? key, this.logEntryId = 0, this.endLogEntryId = 0, this.id = 0})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_LogEventDetailScreenState createState() => _LogEventDetailScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LogEventDetailScreenState extends State<LogEventDetailScreen> {
|
||||||
|
LogEvent? _logEvent;
|
||||||
|
bool _isNew = true;
|
||||||
|
bool _isSaving = false;
|
||||||
|
|
||||||
|
List<BolusProfile> _bolusProfiles = [];
|
||||||
|
List<BasalProfile> _basalProfiles = [];
|
||||||
|
|
||||||
|
final GlobalKey<FormState> _logEventForm = GlobalKey<FormState>();
|
||||||
|
|
||||||
|
late DateTime _time;
|
||||||
|
DateTime? _endTime;
|
||||||
|
|
||||||
|
final _timeController = TextEditingController(text: '');
|
||||||
|
final _endTimeController = TextEditingController(text: '');
|
||||||
|
|
||||||
|
final _dateController = TextEditingController(text: '');
|
||||||
|
final _endDateController = TextEditingController(text: '');
|
||||||
|
|
||||||
|
final _reminderDurationController = TextEditingController(text: '');
|
||||||
|
final _notesController = TextEditingController(text: '');
|
||||||
|
|
||||||
|
LogEventType? _eventType;
|
||||||
|
bool _hasEndTime = false;
|
||||||
|
BolusProfile? _bolusProfile;
|
||||||
|
BasalProfile? _basalProfile;
|
||||||
|
|
||||||
|
List<LogEventType> _logEventTypes = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
reload();
|
||||||
|
|
||||||
|
_bolusProfiles = BolusProfile.getAll();
|
||||||
|
_basalProfiles = BasalProfile.getAll();
|
||||||
|
|
||||||
|
if (widget.id != 0) {
|
||||||
|
_reminderDurationController.text =
|
||||||
|
(_logEvent!.reminderDuration ?? '').toString();
|
||||||
|
_hasEndTime = _logEvent!.hasEndTime;
|
||||||
|
_notesController.text = _logEvent!.notes ?? '';
|
||||||
|
_eventType = _logEvent!.eventType.target;
|
||||||
|
_basalProfile = _logEvent!.basalProfile.target;
|
||||||
|
_bolusProfile = _logEvent!.bolusProfile.target;
|
||||||
|
_time = _logEvent!.time;
|
||||||
|
_endTime = _logEvent!.endTime;
|
||||||
|
} else {
|
||||||
|
_time = DateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
_logEventTypes = LogEventType.getAll();
|
||||||
|
|
||||||
|
updateTime();
|
||||||
|
updateEndTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reload({String? message}) {
|
||||||
|
if (widget.id != 0) {
|
||||||
|
setState(() {
|
||||||
|
_logEvent = LogEvent.get(widget.id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_isNew = _logEvent == null;
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
if (message != null) {
|
||||||
|
var snackBar = SnackBar(
|
||||||
|
content: Text(message),
|
||||||
|
duration: const Duration(seconds: 2),
|
||||||
|
);
|
||||||
|
ScaffoldMessenger.of(context)
|
||||||
|
..removeCurrentSnackBar()
|
||||||
|
..showSnackBar(snackBar);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateTime() {
|
||||||
|
_timeController.text = DateTimeUtils.displayTime(_time);
|
||||||
|
_dateController.text = DateTimeUtils.displayDate(_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateEndTime() {
|
||||||
|
_endTimeController.text = DateTimeUtils.displayTime(_endTime);
|
||||||
|
_endDateController.text = DateTimeUtils.displayDate(_endTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSelectEventType(LogEventType eventType) {
|
||||||
|
setState(() {
|
||||||
|
_eventType = eventType;
|
||||||
|
_hasEndTime = eventType.hasEndTime;
|
||||||
|
if (eventType.basalProfile.target != null) {
|
||||||
|
_basalProfile = eventType.basalProfile.target;
|
||||||
|
}
|
||||||
|
if (eventType.bolusProfile.target != null) {
|
||||||
|
_bolusProfile = eventType.bolusProfile.target;
|
||||||
|
}
|
||||||
|
if (eventType.defaultReminderDuration != null) {
|
||||||
|
_reminderDurationController.text =
|
||||||
|
eventType.defaultReminderDuration.toString();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleSaveAction() async {
|
||||||
|
setState(() {
|
||||||
|
_isSaving = true;
|
||||||
|
});
|
||||||
|
if (_logEventForm.currentState!.validate()) {
|
||||||
|
LogEvent event = LogEvent(
|
||||||
|
id: widget.id,
|
||||||
|
time: _time,
|
||||||
|
endTime: _endTime,
|
||||||
|
hasEndTime: _hasEndTime,
|
||||||
|
reminderDuration: int.tryParse(_reminderDurationController.text),
|
||||||
|
notes: _notesController.text,
|
||||||
|
);
|
||||||
|
event.eventType.target = _eventType;
|
||||||
|
event.basalProfile.target = _basalProfile;
|
||||||
|
event.bolusProfile.target = _bolusProfile;
|
||||||
|
LogEvent.put(event);
|
||||||
|
Navigator.pop(context, '${_isNew ? 'New' : ''} Event Saved');
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
_isSaving = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleCancelAction() {
|
||||||
|
if (showConfirmationDialogOnCancel &&
|
||||||
|
((_isNew &&
|
||||||
|
(_notesController.text != '' ||
|
||||||
|
_eventType != null ||
|
||||||
|
_hasEndTime)) ||
|
||||||
|
(!_isNew &&
|
||||||
|
(_notesController.text != (_logEvent!.notes ?? '') ||
|
||||||
|
_eventType != _logEvent!.eventType.target ||
|
||||||
|
_hasEndTime != _logEvent!.hasEndTime)))) {
|
||||||
|
Dialogs.showCancelConfirmationDialog(
|
||||||
|
context: context,
|
||||||
|
isNew: _isNew,
|
||||||
|
onSave: handleSaveAction,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final now = DateTime.now();
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(_isNew ? 'New Event' : 'Edit Event'),
|
||||||
|
),
|
||||||
|
drawer: const Navigation(currentLocation: LogEventDetailScreen.routeName),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: <Widget>[
|
||||||
|
FormWrapper(
|
||||||
|
formState: _logEventForm,
|
||||||
|
fields: [
|
||||||
|
AutoCompleteDropdownButton<LogEventType>(
|
||||||
|
selectedItem: _eventType,
|
||||||
|
label: 'Event Type',
|
||||||
|
items: _logEventTypes,
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value != null) {
|
||||||
|
onSelectEventType(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 5),
|
||||||
|
child: DateTimeFormField(
|
||||||
|
date: _time,
|
||||||
|
label: _hasEndTime ? 'Start Date' : 'Date',
|
||||||
|
controller: _dateController,
|
||||||
|
onChanged: (newTime) {
|
||||||
|
if (newTime != null) {
|
||||||
|
setState(() {
|
||||||
|
_time = DateTime(
|
||||||
|
newTime.year,
|
||||||
|
newTime.month,
|
||||||
|
newTime.day,
|
||||||
|
_time.hour,
|
||||||
|
_time.minute);
|
||||||
|
});
|
||||||
|
updateTime();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 5),
|
||||||
|
child: TimeOfDayFormField(
|
||||||
|
time: TimeOfDay.fromDateTime(_time),
|
||||||
|
label: _hasEndTime ? 'Start Time' : 'Time',
|
||||||
|
controller: _timeController,
|
||||||
|
onChanged: (newTime) {
|
||||||
|
if (newTime != null) {
|
||||||
|
setState(() {
|
||||||
|
_time = DateTime(
|
||||||
|
_time.year,
|
||||||
|
_time.month,
|
||||||
|
_time.day,
|
||||||
|
newTime.hour,
|
||||||
|
newTime.minute);
|
||||||
|
});
|
||||||
|
updateTime();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
BooleanFormField(
|
||||||
|
value: _hasEndTime,
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_hasEndTime = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
label: 'has end time',
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: _hasEndTime? [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 5),
|
||||||
|
child: DateTimeFormField(
|
||||||
|
date: _endTime ?? now,
|
||||||
|
label: 'End Date',
|
||||||
|
controller: _endDateController,
|
||||||
|
onChanged: (newTime) {
|
||||||
|
if (newTime != null) {
|
||||||
|
setState(() {
|
||||||
|
_endTime = DateTime(
|
||||||
|
newTime.year,
|
||||||
|
newTime.month,
|
||||||
|
newTime.day,
|
||||||
|
_endTime?.hour ?? 0,
|
||||||
|
_endTime?.minute ?? 0);
|
||||||
|
});
|
||||||
|
updateEndTime();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 5),
|
||||||
|
child: TimeOfDayFormField(
|
||||||
|
time: TimeOfDay.fromDateTime(_endTime ?? now),
|
||||||
|
label: 'End Time',
|
||||||
|
controller: _endTimeController,
|
||||||
|
onChanged: (newTime) {
|
||||||
|
if (newTime != null) {
|
||||||
|
setState(() {
|
||||||
|
_endTime = DateTime(
|
||||||
|
_endTime?.year ?? now.year,
|
||||||
|
_endTime?.month ?? now.month,
|
||||||
|
_endTime?.day ?? now.day,
|
||||||
|
newTime.hour,
|
||||||
|
newTime.minute);
|
||||||
|
});
|
||||||
|
updateEndTime();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
controller: _reminderDurationController,
|
||||||
|
keyboardType:
|
||||||
|
const TextInputType.numberWithOptions(),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Default Reminder Duration',
|
||||||
|
suffixText: ' min',
|
||||||
|
enabled: _hasEndTime,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
AutoCompleteDropdownButton<BolusProfile>(
|
||||||
|
selectedItem: _bolusProfile,
|
||||||
|
label: 'Bolus Profile',
|
||||||
|
items: _bolusProfiles,
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_bolusProfile = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
AutoCompleteDropdownButton<BasalProfile>(
|
||||||
|
selectedItem: _basalProfile,
|
||||||
|
label: 'Basal Profile',
|
||||||
|
items: _basalProfiles,
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_basalProfile = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
TextFormField(
|
||||||
|
controller: _notesController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Notes',
|
||||||
|
alignLabelWithHint: true,
|
||||||
|
),
|
||||||
|
keyboardType: TextInputType.multiline,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
bottomNavigationBar: DetailBottomRow(
|
||||||
|
onCancel: handleCancelAction,
|
||||||
|
onSave: _isSaving ? null : handleSaveAction,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,31 +1,35 @@
|
|||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/config.dart';
|
||||||
import 'package:diameter/models/log_entry.dart';
|
|
||||||
import 'package:diameter/models/log_event.dart';
|
import 'package:diameter/models/log_event.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_event_detail.dart';
|
import 'package:diameter/screens/log/log_event/log_event_detail.dart';
|
||||||
import 'package:diameter/utils/date_time_utils.dart';
|
import 'package:diameter/utils/date_time_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:diameter/navigation.dart';
|
||||||
|
|
||||||
class LogEventListScreen extends StatefulWidget {
|
class LogEventListScreen extends StatefulWidget {
|
||||||
final LogEntry? logEntry;
|
static const String routeName = '/log-events';
|
||||||
final List<LogEvent> logEvents;
|
const LogEventListScreen({Key? key}) : super(key: key);
|
||||||
final List<LogEvent> activeEvents;
|
|
||||||
final Function()? reload;
|
|
||||||
|
|
||||||
const LogEventListScreen(
|
|
||||||
{Key? key, this.logEntry, this.logEvents = const [], this.activeEvents = const [], this.reload})
|
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_LogEventListScreenState createState() => _LogEventListScreenState();
|
_LogEventListScreenState createState() => _LogEventListScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LogEventListScreenState extends State<LogEventListScreen> {
|
class _LogEventListScreenState extends State<LogEventListScreen> {
|
||||||
void reload({String? message}) {
|
List<LogEvent> _activeEvents = [];
|
||||||
if (widget.reload != null) {
|
late Map<DateTime, List<LogEvent>> _logEventDailyMap;
|
||||||
widget.reload!();
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reload({String? message}) {
|
||||||
|
setState(() {
|
||||||
|
_activeEvents = LogEvent.getAllActiveForTime(DateTime.now());
|
||||||
|
_logEventDailyMap = LogEvent.getDailyEntryMap();
|
||||||
|
});
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
var snackBar = SnackBar(
|
var snackBar = SnackBar(
|
||||||
@ -39,12 +43,22 @@ class _LogEventListScreenState extends State<LogEventListScreen> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleAddNewEvent() async {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return const LogEventDetailScreen();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
).then((message) => reload(message: message));
|
||||||
|
}
|
||||||
|
|
||||||
void handleEditAction(LogEvent event) {
|
void handleEditAction(LogEvent event) {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => LogEventDetailScreen(
|
builder: (context) => LogEventDetailScreen(
|
||||||
logEntryId: widget.logEntry?.id ?? 0,
|
|
||||||
id: event.id,
|
id: event.id,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -70,8 +84,6 @@ class _LogEventListScreenState extends State<LogEventListScreen> {
|
|||||||
|
|
||||||
void onStop(LogEvent event) async {
|
void onStop(LogEvent event) async {
|
||||||
event.endTime = DateTime.now();
|
event.endTime = DateTime.now();
|
||||||
event.endLogEntry.target =
|
|
||||||
LogEntry.get(widget.logEntry?.id ?? 0) ?? LogEntry(time: DateTime.now());
|
|
||||||
LogEvent.put(event);
|
LogEvent.put(event);
|
||||||
reload(message: 'Event ended');
|
reload(message: 'Event ended');
|
||||||
}
|
}
|
||||||
@ -89,21 +101,41 @@ class _LogEventListScreenState extends State<LogEventListScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Scaffold(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
appBar: AppBar(
|
||||||
|
title: const Text('Log Events'),
|
||||||
|
actions: <Widget>[
|
||||||
|
IconButton(onPressed: reload, icon: const Icon(Icons.refresh))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
drawer: const Navigation(currentLocation: LogEventListScreen.routeName),
|
||||||
|
body: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: (widget.logEvents.isNotEmpty ||
|
child: _logEventDailyMap.isNotEmpty
|
||||||
widget.activeEvents.isNotEmpty)
|
? SingleChildScrollView(
|
||||||
|
child: ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
itemCount: _logEventDailyMap.length,
|
||||||
|
itemBuilder: (context, dateIndex) {
|
||||||
|
List<DateTime?> dateList = <DateTime?>[null] +
|
||||||
|
_logEventDailyMap.keys.toList();
|
||||||
|
final date = dateList[dateIndex];
|
||||||
|
final eventList = date != null ? _logEventDailyMap[date] : _activeEvents;
|
||||||
|
return ListBody(
|
||||||
|
children: [
|
||||||
|
Text(DateTimeUtils.displayDate(date, fallback: 'Active Events')),
|
||||||
|
eventList != null && eventList.isNotEmpty
|
||||||
? ListView.builder(
|
? ListView.builder(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
itemCount: widget.logEvents.length +
|
itemCount: eventList.length,
|
||||||
widget.activeEvents.length,
|
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final event = (widget.logEvents +
|
final event = eventList[index];
|
||||||
widget.activeEvents)[index];
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
handleEditAction(event);
|
handleEditAction(event);
|
||||||
@ -138,13 +170,21 @@ class _LogEventListScreenState extends State<LogEventListScreen> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
})
|
}) : Container(),
|
||||||
: Center(
|
],
|
||||||
child: Text(widget.logEntry == null ? 'There are no active Events!'
|
);
|
||||||
: 'You have not added any Events to this Log Entry yet!'),
|
},
|
||||||
|
),
|
||||||
|
) : const Center(
|
||||||
|
child: Text('There are no Events!'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: handleAddNewEvent,
|
||||||
|
child: const Icon(Icons.add),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,17 +9,17 @@ import 'package:diameter/models/log_event_type.dart';
|
|||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class LogEventTypeDetailScreen extends StatefulWidget {
|
class EventTypeDetailScreen extends StatefulWidget {
|
||||||
static const String routeName = '/log-event-type';
|
static const String routeName = '/log-event-type';
|
||||||
final int id;
|
final int id;
|
||||||
const LogEventTypeDetailScreen({Key? key, this.id = 0}) : super(key: key);
|
const EventTypeDetailScreen({Key? key, this.id = 0}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_LogEventTypeDetailScreenState createState() =>
|
_EventTypeDetailScreenState createState() =>
|
||||||
_LogEventTypeDetailScreenState();
|
_EventTypeDetailScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LogEventTypeDetailScreenState extends State<LogEventTypeDetailScreen> {
|
class _EventTypeDetailScreenState extends State<EventTypeDetailScreen> {
|
||||||
LogEventType? _logEventType;
|
LogEventType? _logEventType;
|
||||||
bool _isNew = true;
|
bool _isNew = true;
|
||||||
bool _isSaving = false;
|
bool _isSaving = false;
|
||||||
@ -120,7 +120,7 @@ class _LogEventTypeDetailScreenState extends State<LogEventTypeDetailScreen> {
|
|||||||
title: Text(_isNew ? 'New Log Event Type' : _logEventType!.value),
|
title: Text(_isNew ? 'New Log Event Type' : _logEventType!.value),
|
||||||
),
|
),
|
||||||
drawer:
|
drawer:
|
||||||
const Navigation(currentLocation: LogEventTypeDetailScreen.routeName),
|
const Navigation(currentLocation: EventTypeDetailScreen.routeName),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
@ -1,6 +1,6 @@
|
|||||||
import 'package:diameter/models/log_event_type.dart';
|
import 'package:diameter/models/log_event_type.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/screens/log/log_event_type_detail.dart';
|
import 'package:diameter/screens/log/log_event/log_event_type_detail.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class LogEventTypeListScreen extends StatefulWidget {
|
class LogEventTypeListScreen extends StatefulWidget {
|
||||||
@ -60,7 +60,7 @@ class _LogEventTypeListScreenState extends State<LogEventTypeListScreen> {
|
|||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
LogEventTypeDetailScreen(
|
EventTypeDetailScreen(
|
||||||
id: logEventType.id),
|
id: logEventType.id),
|
||||||
),
|
),
|
||||||
).then((message) => reload(message: message));
|
).then((message) => reload(message: message));
|
||||||
@ -73,10 +73,8 @@ class _LogEventTypeListScreenState extends State<LogEventTypeListScreen> {
|
|||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
LogEventType.remove(logEventType.id);
|
LogEventType.remove(logEventType.id);
|
||||||
// await logEventType.delete().then((_) {
|
|
||||||
reload(
|
reload(
|
||||||
message: 'Log Event Type deleted');
|
message: 'Log Event Type deleted');
|
||||||
// });
|
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.delete,
|
icon: const Icon(Icons.delete,
|
||||||
color: Colors.blue),
|
color: Colors.blue),
|
||||||
@ -96,7 +94,7 @@ class _LogEventTypeListScreenState extends State<LogEventTypeListScreen> {
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => const LogEventTypeDetailScreen(),
|
builder: (context) => const EventTypeDetailScreen(),
|
||||||
),
|
),
|
||||||
).then((message) => reload(message: message));
|
).then((message) => reload(message: message));
|
||||||
},
|
},
|
Loading…
Reference in New Issue
Block a user