diff --git a/lib/models/log_entry.dart b/lib/models/log_entry.dart index bfefcef..b5d686e 100644 --- a/lib/models/log_entry.dart +++ b/lib/models/log_entry.dart @@ -42,11 +42,25 @@ class LogEntry { notes = object.get('notes'); } + static Future>> createDailyEntryMap() async { + Map> dateMap = >{}; + List entries = await fetchAll(); + DateTime? date; + + for (LogEntry entry in entries) { + date = DateTime.utc(entry.time.year, entry.time.month, entry.time.day); + dateMap.putIfAbsent(date, () => []).add(entry); + } + + return dateMap; + } + static Future> fetchAllForRange(DateTimeRange range) async { QueryBuilder query = QueryBuilder(ParseObject('LogEntry')) ..whereGreaterThanOrEqualsTo('time', range.start) - ..whereLessThanOrEqualTo('time', range.end); + ..whereLessThanOrEqualTo('time', range.end) + ..orderByAscending('time'); final ParseResponse apiResponse = await query.query(); if (apiResponse.success && apiResponse.results != null) { @@ -59,8 +73,11 @@ class LogEntry { } static Future> fetchAll() async { + // TODO: consider adding pagination/lazy loading here QueryBuilder query = - QueryBuilder(ParseObject('LogEntry')); + QueryBuilder(ParseObject('LogEntry')) + ..orderByAscending('time'); + ; final ParseResponse apiResponse = await query.query(); if (apiResponse.success && apiResponse.results != null) { diff --git a/lib/screens/log/log.dart b/lib/screens/log/log.dart index 81316cc..367c8e1 100644 --- a/lib/screens/log/log.dart +++ b/lib/screens/log/log.dart @@ -16,11 +16,11 @@ class LogScreen extends StatefulWidget { } class _LogScreenState extends State { - late Future?> _logEntries; + late Future>?> _logEntryDailyMap; void refresh({String? message}) { setState(() { - _logEntries = LogEntry.fetchAll(); + _logEntryDailyMap = LogEntry.createDailyEntryMap(); }); setState(() { if (message != null) { @@ -68,65 +68,89 @@ class _LogScreenState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Expanded( - child: FutureBuilder?>( - future: _logEntries, - builder: (context, snapshot) { - return ViewWithProgressIndicator( - snapshot: snapshot, - child: snapshot.data == null || snapshot.data!.isEmpty - ? Row( - mainAxisAlignment: MainAxisAlignment.center, - children: const [ - Padding( - padding: EdgeInsets.all(10.0), - child: Text('No Log Entries'), - ), - ], - ) - : ListView.builder( - padding: const EdgeInsets.all(10.0), - itemCount: - snapshot.data != null ? snapshot.data!.length : 0, - itemBuilder: (context, index) { - final logEntry = snapshot.data![index]; - // TODO: split entries by day - return ListTile( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - LogEntryScreen(entry: logEntry), - ), - ).then((message) => refresh(message: message)); - }, - title: - // TODO: only display time here - Text(DateTimeUtils.displayDateTime( - logEntry.time)), - // TODO: display according to settings - // TODO: add additional fields (event icons...) - // TODO: display glucose in colors according to target settings - subtitle: Text(logEntry.mgPerDl != null - ? '${logEntry.mgPerDl.toString()} mg/dl' - : ''), - trailing: Row( - mainAxisSize: MainAxisSize.min, - children: [ - IconButton( - onPressed: () => - handleDeleteAction(logEntry), - icon: const Icon(Icons.delete, - color: Colors.blue), - ) - ], + child: FutureBuilder>?>( + future: _logEntryDailyMap, + builder: (context, snapshot) { + return ViewWithProgressIndicator( + snapshot: snapshot, + child: snapshot.data == null || snapshot.data!.isEmpty + ? Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Padding( + padding: EdgeInsets.all(10.0), + child: Text('No Log Entries'), ), - ); - }, - ), - ); - }, - ), + ], + ) + : SingleChildScrollView( + child: ListView.builder( + shrinkWrap: true, + padding: const EdgeInsets.all(10.0), + itemCount: snapshot.data != null + ? snapshot.data!.length + : 0, + itemBuilder: (context, dateIndex) { + List dateList = + snapshot.data!.keys.toList(); + dateList.sort((a, b) => a.compareTo(b) * -1); + final date = dateList[dateIndex]; + final entryList = snapshot.data![date]; + return ListBody( + children: [ + Text(DateTimeUtils.displayDate(date)), + entryList != null && entryList.isNotEmpty + ? ListView.builder( + shrinkWrap: true, + itemCount: entryList.length, + itemBuilder: (context, index) { + final logEntry = entryList[index]; + return ListTile( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + LogEntryScreen( + entry: logEntry), + ), + ).then((message) => refresh( + message: message)); + }, + title: Text( + DateTimeUtils.displayTime( + logEntry.time)), + // TODO: add additional fields (event icons...) + // TODO: display glucose in colors according to target settings + subtitle: Text(logEntry + .mgPerDl != + null + ? '${logEntry.mgPerDl.toString()} mg/dl' + : ''), + trailing: Row( + mainAxisSize: + MainAxisSize.min, + children: [ + IconButton( + onPressed: () => + handleDeleteAction( + logEntry), + icon: const Icon( + Icons.delete, + color: Colors.blue), + ) + ], + ), + ); + }) + : Container(), + ], + ); + }, + ), + ), + ); + }), ), ], ),