flutterdartdatedatetimeobjectbox

How do I group entries by date?


The problem is that the date appears between everysingle entry, all of the entries are saved in an object box data base and have DateTime saved under date. Im pretty new to flutter and im still learning so if anyone could show me where to learn this or if anyone has any ideas on how I would do this it would be so very appreciated. Thank you in advance :)

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:the_holy_trinity/libraries/styles/decorations.dart';
import 'package:the_holy_trinity/libraries/styles/texts.dart';
import 'package:the_holy_trinity/main.dart';
import 'package:the_holy_trinity/models/note_model.dart';
import 'package:the_holy_trinity/screens/diary_page/view_note_page.dart';
import 'package:the_holy_trinity/services/objectbox_helper.dart';

class DiaryPage extends StatefulWidget {
  final ObjectBox objectBox;

  const DiaryPage({Key? key, required this.objectBox}) : super(key: key);
  
  @override
  State<DiaryPage> createState() => _DiaryPageState();
}

class _DiaryPageState extends State<DiaryPage> {
  
  @override
  Widget build(BuildContext context) {

    return Scaffold(
        body: Container(
          decoration: blankDecor(),
          height: MediaQuery.of(context).size.height,
          child: Column(
          children: [
            SizedBox(height: MediaQuery.of(context).size.height * 0.05,),
            Expanded(
              child: StreamBuilder<List<Note>>(
              stream: objectBox.getNotes(),
              builder:(context, snapshot) => ListView.builder(
                shrinkWrap: true,
                padding: const EdgeInsets.symmetric(horizontal: 20.0),
                itemCount: snapshot.hasData ? snapshot.data!.length : 1,
                itemBuilder: (context, index) {
                  if(snapshot.data == null) {
                    return SizedBox(
                      height: MediaQuery.of(context).size.height,
                      width: MediaQuery.of(context).size.width,
                      child: BodyStyle('No notes!'),
                    );
                  } else {
                    DateFormat formatter = DateFormat('dd MMM yyyy');
                    String formattedDate = formatter.format(snapshot.data![index].date);
                  return Column(
                    children: [
                  BodyStyle(formattedDate),
                  Card(
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(8),
                    ),
                    color: const Color.fromARGB(255, 141, 189, 131),
                    child: InkWell(
                      child: ListTile(
                        contentPadding: const EdgeInsets.all(15.0),
                        title: CardTextStyle(
                          snapshot.data![index].content,
                          maxLines: 3,
                        ),
                    ),
                    onTap:() async {
                      final toEditNoteId = snapshot.data![index].id;
                      Navigator.of(context).push(
                        MaterialPageRoute(
                          builder: (context) => ViewNotePage(noteId: toEditNoteId, objectBox: objectBox)
                          ),
                      );
                    }
                    ),
                  ),
                  const SizedBox(
                    height: 20,
                  ),
                    ]
                  );
                }
                },
              ),
            )
            ),
          ],
        ),
        ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
      floatingActionButton: FloatingActionButton(
        backgroundColor: const Color.fromARGB(255, 40, 94, 33),
          onPressed: (){
            Navigator.pushNamed(context, '/newNote', arguments: {objectBox: objectBox},
            );
          },
        child: const Icon(Icons.add, color: Colors.white, size: 20,)
          ),
    );
  }

This is what it looks like now

and I would like for there only to be a divider between entries from different dates


Solution

  • Me again, what I ended up using was a seperated list. Basically what this code does is it takes all the entries from the database, and then gets their dates and if two or more of the dates are the same it puts them in a 'group' which you can use to mark the points in between each date

    I hope this helps someone because I know I really struggled to figure this out despite how obvious it seems now :)

    child: StreamBuilder < List < Note >> (
      stream: objectBox.getNotes(),
      builder: (context, snapshot) => ListView.separated(
        separatorBuilder: (context, index) => Divider(),
        shrinkWrap: true,
        padding: const EdgeInsets.only(top: 20.0, bottom: 0.0, left: 20, right: 20),
          itemCount: snapshot.hasData ? snapshot.data!.length + 1 : 0,
          itemBuilder: (context, index) {
            if (snapshot.hasData) {
              final notes = snapshot.data!;
              final groupedNotes = groupBy < Note, String > (
                notes,
                (note) => DateFormat('dd MMM yyyy').format(note.date),
              );
              if (groupedNotes.keys.length > index) {
                final date = groupedNotes.keys.elementAt(index);
                final dateNotes = groupedNotes[date] !;
                return Column(
                  children: [
                    BodyStyle(date),
                    const Divider(),
                      ListView.builder(
                        shrinkWrap: true,
                        physics: const NeverScrollableScrollPhysics(),
                          itemCount: dateNotes.length,
                          itemBuilder: (context, innerIndex) => Card(
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(8),
                            ),
                            color: const Color.fromARGB(255, 141, 189, 131),
                              child: InkWell(
                                child: ListTile(
                                  contentPadding: const EdgeInsets.all(15.0),
                                    title: CardTextStyle(
                                      dateNotes[innerIndex].content,
                                      maxLines: 3,
                                    ),
                                ),
                                onTap: () async {
                                  int noteId = dateNotes[innerIndex].id;
                                  await Navigator.of(context).push(
                                    MaterialPageRoute(
                                      builder: ((context) => ViewNotePage(noteId: noteId, objectBox: objectBox))
                                    )
                                  );
                                },
                              ),
                          ),
                      ),
                  ],
                );
              } else {
                return null;
              }
            }
          }
      ),
    ),