feat: implement multi-step mood logging wizard

Adds sleep/energy/positivity/self-worth tracking columns to the database
(schema v2 migration), a new 5-option StepScale widget, per-answer chips
at the top of the screen, a 2×2 activity grid chip, and a full step-by-step
wizard flow: mood → sleep (first entry today only) → energy → positivity →
self-worth → activities → review+save.
This commit is contained in:
2026-04-26 12:14:45 +10:00
parent 59597c7a4f
commit 6f3fb74e7e
10 changed files with 1142 additions and 129 deletions
+255 -9
View File
@@ -43,9 +43,42 @@ class $MoodEntriesTable extends MoodEntries
type: DriftSqlType.dateTime,
requiredDuringInsert: false,
defaultValue: currentDateAndTime);
static const VerificationMeta _sleepMinutesMeta =
const VerificationMeta('sleepMinutes');
@override
List<GeneratedColumn> get $columns =>
[id, timestamp, moodLevel, note, createdAt];
late final GeneratedColumn<int> sleepMinutes = GeneratedColumn<int>(
'sleep_minutes', aliasedName, true,
type: DriftSqlType.int, requiredDuringInsert: false);
static const VerificationMeta _energyLevelMeta =
const VerificationMeta('energyLevel');
@override
late final GeneratedColumn<int> energyLevel = GeneratedColumn<int>(
'energy_level', aliasedName, true,
type: DriftSqlType.int, requiredDuringInsert: false);
static const VerificationMeta _positivityLevelMeta =
const VerificationMeta('positivityLevel');
@override
late final GeneratedColumn<int> positivityLevel = GeneratedColumn<int>(
'positivity_level', aliasedName, true,
type: DriftSqlType.int, requiredDuringInsert: false);
static const VerificationMeta _selfWorthLevelMeta =
const VerificationMeta('selfWorthLevel');
@override
late final GeneratedColumn<int> selfWorthLevel = GeneratedColumn<int>(
'self_worth_level', aliasedName, true,
type: DriftSqlType.int, requiredDuringInsert: false);
@override
List<GeneratedColumn> get $columns => [
id,
timestamp,
moodLevel,
note,
createdAt,
sleepMinutes,
energyLevel,
positivityLevel,
selfWorthLevel
];
@override
String get aliasedName => _alias ?? actualTableName;
@override
@@ -79,6 +112,30 @@ class $MoodEntriesTable extends MoodEntries
context.handle(_createdAtMeta,
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta));
}
if (data.containsKey('sleep_minutes')) {
context.handle(
_sleepMinutesMeta,
sleepMinutes.isAcceptableOrUnknown(
data['sleep_minutes']!, _sleepMinutesMeta));
}
if (data.containsKey('energy_level')) {
context.handle(
_energyLevelMeta,
energyLevel.isAcceptableOrUnknown(
data['energy_level']!, _energyLevelMeta));
}
if (data.containsKey('positivity_level')) {
context.handle(
_positivityLevelMeta,
positivityLevel.isAcceptableOrUnknown(
data['positivity_level']!, _positivityLevelMeta));
}
if (data.containsKey('self_worth_level')) {
context.handle(
_selfWorthLevelMeta,
selfWorthLevel.isAcceptableOrUnknown(
data['self_worth_level']!, _selfWorthLevelMeta));
}
return context;
}
@@ -98,6 +155,14 @@ class $MoodEntriesTable extends MoodEntries
.read(DriftSqlType.string, data['${effectivePrefix}note']),
createdAt: attachedDatabase.typeMapping
.read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!,
sleepMinutes: attachedDatabase.typeMapping
.read(DriftSqlType.int, data['${effectivePrefix}sleep_minutes']),
energyLevel: attachedDatabase.typeMapping
.read(DriftSqlType.int, data['${effectivePrefix}energy_level']),
positivityLevel: attachedDatabase.typeMapping
.read(DriftSqlType.int, data['${effectivePrefix}positivity_level']),
selfWorthLevel: attachedDatabase.typeMapping
.read(DriftSqlType.int, data['${effectivePrefix}self_worth_level']),
);
}
@@ -113,12 +178,20 @@ class MoodEntry extends DataClass implements Insertable<MoodEntry> {
final int moodLevel;
final String? note;
final DateTime createdAt;
final int? sleepMinutes;
final int? energyLevel;
final int? positivityLevel;
final int? selfWorthLevel;
const MoodEntry(
{required this.id,
required this.timestamp,
required this.moodLevel,
this.note,
required this.createdAt});
required this.createdAt,
this.sleepMinutes,
this.energyLevel,
this.positivityLevel,
this.selfWorthLevel});
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
@@ -129,6 +202,18 @@ class MoodEntry extends DataClass implements Insertable<MoodEntry> {
map['note'] = Variable<String>(note);
}
map['created_at'] = Variable<DateTime>(createdAt);
if (!nullToAbsent || sleepMinutes != null) {
map['sleep_minutes'] = Variable<int>(sleepMinutes);
}
if (!nullToAbsent || energyLevel != null) {
map['energy_level'] = Variable<int>(energyLevel);
}
if (!nullToAbsent || positivityLevel != null) {
map['positivity_level'] = Variable<int>(positivityLevel);
}
if (!nullToAbsent || selfWorthLevel != null) {
map['self_worth_level'] = Variable<int>(selfWorthLevel);
}
return map;
}
@@ -139,6 +224,18 @@ class MoodEntry extends DataClass implements Insertable<MoodEntry> {
moodLevel: Value(moodLevel),
note: note == null && nullToAbsent ? const Value.absent() : Value(note),
createdAt: Value(createdAt),
sleepMinutes: sleepMinutes == null && nullToAbsent
? const Value.absent()
: Value(sleepMinutes),
energyLevel: energyLevel == null && nullToAbsent
? const Value.absent()
: Value(energyLevel),
positivityLevel: positivityLevel == null && nullToAbsent
? const Value.absent()
: Value(positivityLevel),
selfWorthLevel: selfWorthLevel == null && nullToAbsent
? const Value.absent()
: Value(selfWorthLevel),
);
}
@@ -151,6 +248,10 @@ class MoodEntry extends DataClass implements Insertable<MoodEntry> {
moodLevel: serializer.fromJson<int>(json['moodLevel']),
note: serializer.fromJson<String?>(json['note']),
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
sleepMinutes: serializer.fromJson<int?>(json['sleepMinutes']),
energyLevel: serializer.fromJson<int?>(json['energyLevel']),
positivityLevel: serializer.fromJson<int?>(json['positivityLevel']),
selfWorthLevel: serializer.fromJson<int?>(json['selfWorthLevel']),
);
}
@override
@@ -162,6 +263,10 @@ class MoodEntry extends DataClass implements Insertable<MoodEntry> {
'moodLevel': serializer.toJson<int>(moodLevel),
'note': serializer.toJson<String?>(note),
'createdAt': serializer.toJson<DateTime>(createdAt),
'sleepMinutes': serializer.toJson<int?>(sleepMinutes),
'energyLevel': serializer.toJson<int?>(energyLevel),
'positivityLevel': serializer.toJson<int?>(positivityLevel),
'selfWorthLevel': serializer.toJson<int?>(selfWorthLevel),
};
}
@@ -170,13 +275,25 @@ class MoodEntry extends DataClass implements Insertable<MoodEntry> {
DateTime? timestamp,
int? moodLevel,
Value<String?> note = const Value.absent(),
DateTime? createdAt}) =>
DateTime? createdAt,
Value<int?> sleepMinutes = const Value.absent(),
Value<int?> energyLevel = const Value.absent(),
Value<int?> positivityLevel = const Value.absent(),
Value<int?> selfWorthLevel = const Value.absent()}) =>
MoodEntry(
id: id ?? this.id,
timestamp: timestamp ?? this.timestamp,
moodLevel: moodLevel ?? this.moodLevel,
note: note.present ? note.value : this.note,
createdAt: createdAt ?? this.createdAt,
sleepMinutes:
sleepMinutes.present ? sleepMinutes.value : this.sleepMinutes,
energyLevel: energyLevel.present ? energyLevel.value : this.energyLevel,
positivityLevel: positivityLevel.present
? positivityLevel.value
: this.positivityLevel,
selfWorthLevel:
selfWorthLevel.present ? selfWorthLevel.value : this.selfWorthLevel,
);
MoodEntry copyWithCompanion(MoodEntriesCompanion data) {
return MoodEntry(
@@ -185,6 +302,17 @@ class MoodEntry extends DataClass implements Insertable<MoodEntry> {
moodLevel: data.moodLevel.present ? data.moodLevel.value : this.moodLevel,
note: data.note.present ? data.note.value : this.note,
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
sleepMinutes: data.sleepMinutes.present
? data.sleepMinutes.value
: this.sleepMinutes,
energyLevel:
data.energyLevel.present ? data.energyLevel.value : this.energyLevel,
positivityLevel: data.positivityLevel.present
? data.positivityLevel.value
: this.positivityLevel,
selfWorthLevel: data.selfWorthLevel.present
? data.selfWorthLevel.value
: this.selfWorthLevel,
);
}
@@ -195,13 +323,18 @@ class MoodEntry extends DataClass implements Insertable<MoodEntry> {
..write('timestamp: $timestamp, ')
..write('moodLevel: $moodLevel, ')
..write('note: $note, ')
..write('createdAt: $createdAt')
..write('createdAt: $createdAt, ')
..write('sleepMinutes: $sleepMinutes, ')
..write('energyLevel: $energyLevel, ')
..write('positivityLevel: $positivityLevel, ')
..write('selfWorthLevel: $selfWorthLevel')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(id, timestamp, moodLevel, note, createdAt);
int get hashCode => Object.hash(id, timestamp, moodLevel, note, createdAt,
sleepMinutes, energyLevel, positivityLevel, selfWorthLevel);
@override
bool operator ==(Object other) =>
identical(this, other) ||
@@ -210,7 +343,11 @@ class MoodEntry extends DataClass implements Insertable<MoodEntry> {
other.timestamp == this.timestamp &&
other.moodLevel == this.moodLevel &&
other.note == this.note &&
other.createdAt == this.createdAt);
other.createdAt == this.createdAt &&
other.sleepMinutes == this.sleepMinutes &&
other.energyLevel == this.energyLevel &&
other.positivityLevel == this.positivityLevel &&
other.selfWorthLevel == this.selfWorthLevel);
}
class MoodEntriesCompanion extends UpdateCompanion<MoodEntry> {
@@ -219,12 +356,20 @@ class MoodEntriesCompanion extends UpdateCompanion<MoodEntry> {
final Value<int> moodLevel;
final Value<String?> note;
final Value<DateTime> createdAt;
final Value<int?> sleepMinutes;
final Value<int?> energyLevel;
final Value<int?> positivityLevel;
final Value<int?> selfWorthLevel;
const MoodEntriesCompanion({
this.id = const Value.absent(),
this.timestamp = const Value.absent(),
this.moodLevel = const Value.absent(),
this.note = const Value.absent(),
this.createdAt = const Value.absent(),
this.sleepMinutes = const Value.absent(),
this.energyLevel = const Value.absent(),
this.positivityLevel = const Value.absent(),
this.selfWorthLevel = const Value.absent(),
});
MoodEntriesCompanion.insert({
this.id = const Value.absent(),
@@ -232,6 +377,10 @@ class MoodEntriesCompanion extends UpdateCompanion<MoodEntry> {
required int moodLevel,
this.note = const Value.absent(),
this.createdAt = const Value.absent(),
this.sleepMinutes = const Value.absent(),
this.energyLevel = const Value.absent(),
this.positivityLevel = const Value.absent(),
this.selfWorthLevel = const Value.absent(),
}) : timestamp = Value(timestamp),
moodLevel = Value(moodLevel);
static Insertable<MoodEntry> custom({
@@ -240,6 +389,10 @@ class MoodEntriesCompanion extends UpdateCompanion<MoodEntry> {
Expression<int>? moodLevel,
Expression<String>? note,
Expression<DateTime>? createdAt,
Expression<int>? sleepMinutes,
Expression<int>? energyLevel,
Expression<int>? positivityLevel,
Expression<int>? selfWorthLevel,
}) {
return RawValuesInsertable({
if (id != null) 'id': id,
@@ -247,6 +400,10 @@ class MoodEntriesCompanion extends UpdateCompanion<MoodEntry> {
if (moodLevel != null) 'mood_level': moodLevel,
if (note != null) 'note': note,
if (createdAt != null) 'created_at': createdAt,
if (sleepMinutes != null) 'sleep_minutes': sleepMinutes,
if (energyLevel != null) 'energy_level': energyLevel,
if (positivityLevel != null) 'positivity_level': positivityLevel,
if (selfWorthLevel != null) 'self_worth_level': selfWorthLevel,
});
}
@@ -255,13 +412,21 @@ class MoodEntriesCompanion extends UpdateCompanion<MoodEntry> {
Value<DateTime>? timestamp,
Value<int>? moodLevel,
Value<String?>? note,
Value<DateTime>? createdAt}) {
Value<DateTime>? createdAt,
Value<int?>? sleepMinutes,
Value<int?>? energyLevel,
Value<int?>? positivityLevel,
Value<int?>? selfWorthLevel}) {
return MoodEntriesCompanion(
id: id ?? this.id,
timestamp: timestamp ?? this.timestamp,
moodLevel: moodLevel ?? this.moodLevel,
note: note ?? this.note,
createdAt: createdAt ?? this.createdAt,
sleepMinutes: sleepMinutes ?? this.sleepMinutes,
energyLevel: energyLevel ?? this.energyLevel,
positivityLevel: positivityLevel ?? this.positivityLevel,
selfWorthLevel: selfWorthLevel ?? this.selfWorthLevel,
);
}
@@ -283,6 +448,18 @@ class MoodEntriesCompanion extends UpdateCompanion<MoodEntry> {
if (createdAt.present) {
map['created_at'] = Variable<DateTime>(createdAt.value);
}
if (sleepMinutes.present) {
map['sleep_minutes'] = Variable<int>(sleepMinutes.value);
}
if (energyLevel.present) {
map['energy_level'] = Variable<int>(energyLevel.value);
}
if (positivityLevel.present) {
map['positivity_level'] = Variable<int>(positivityLevel.value);
}
if (selfWorthLevel.present) {
map['self_worth_level'] = Variable<int>(selfWorthLevel.value);
}
return map;
}
@@ -293,7 +470,11 @@ class MoodEntriesCompanion extends UpdateCompanion<MoodEntry> {
..write('timestamp: $timestamp, ')
..write('moodLevel: $moodLevel, ')
..write('note: $note, ')
..write('createdAt: $createdAt')
..write('createdAt: $createdAt, ')
..write('sleepMinutes: $sleepMinutes, ')
..write('energyLevel: $energyLevel, ')
..write('positivityLevel: $positivityLevel, ')
..write('selfWorthLevel: $selfWorthLevel')
..write(')'))
.toString();
}
@@ -1903,6 +2084,10 @@ typedef $$MoodEntriesTableCreateCompanionBuilder = MoodEntriesCompanion
required int moodLevel,
Value<String?> note,
Value<DateTime> createdAt,
Value<int?> sleepMinutes,
Value<int?> energyLevel,
Value<int?> positivityLevel,
Value<int?> selfWorthLevel,
});
typedef $$MoodEntriesTableUpdateCompanionBuilder = MoodEntriesCompanion
Function({
@@ -1911,6 +2096,10 @@ typedef $$MoodEntriesTableUpdateCompanionBuilder = MoodEntriesCompanion
Value<int> moodLevel,
Value<String?> note,
Value<DateTime> createdAt,
Value<int?> sleepMinutes,
Value<int?> energyLevel,
Value<int?> positivityLevel,
Value<int?> selfWorthLevel,
});
final class $$MoodEntriesTableReferences
@@ -1974,6 +2163,20 @@ class $$MoodEntriesTableFilterComposer
ColumnFilters<DateTime> get createdAt => $composableBuilder(
column: $table.createdAt, builder: (column) => ColumnFilters(column));
ColumnFilters<int> get sleepMinutes => $composableBuilder(
column: $table.sleepMinutes, builder: (column) => ColumnFilters(column));
ColumnFilters<int> get energyLevel => $composableBuilder(
column: $table.energyLevel, builder: (column) => ColumnFilters(column));
ColumnFilters<int> get positivityLevel => $composableBuilder(
column: $table.positivityLevel,
builder: (column) => ColumnFilters(column));
ColumnFilters<int> get selfWorthLevel => $composableBuilder(
column: $table.selfWorthLevel,
builder: (column) => ColumnFilters(column));
Expression<bool> entryActivitiesRefs(
Expression<bool> Function($$EntryActivitiesTableFilterComposer f) f) {
final $$EntryActivitiesTableFilterComposer composer = $composerBuilder(
@@ -2040,6 +2243,21 @@ class $$MoodEntriesTableOrderingComposer
ColumnOrderings<DateTime> get createdAt => $composableBuilder(
column: $table.createdAt, builder: (column) => ColumnOrderings(column));
ColumnOrderings<int> get sleepMinutes => $composableBuilder(
column: $table.sleepMinutes,
builder: (column) => ColumnOrderings(column));
ColumnOrderings<int> get energyLevel => $composableBuilder(
column: $table.energyLevel, builder: (column) => ColumnOrderings(column));
ColumnOrderings<int> get positivityLevel => $composableBuilder(
column: $table.positivityLevel,
builder: (column) => ColumnOrderings(column));
ColumnOrderings<int> get selfWorthLevel => $composableBuilder(
column: $table.selfWorthLevel,
builder: (column) => ColumnOrderings(column));
}
class $$MoodEntriesTableAnnotationComposer
@@ -2066,6 +2284,18 @@ class $$MoodEntriesTableAnnotationComposer
GeneratedColumn<DateTime> get createdAt =>
$composableBuilder(column: $table.createdAt, builder: (column) => column);
GeneratedColumn<int> get sleepMinutes => $composableBuilder(
column: $table.sleepMinutes, builder: (column) => column);
GeneratedColumn<int> get energyLevel => $composableBuilder(
column: $table.energyLevel, builder: (column) => column);
GeneratedColumn<int> get positivityLevel => $composableBuilder(
column: $table.positivityLevel, builder: (column) => column);
GeneratedColumn<int> get selfWorthLevel => $composableBuilder(
column: $table.selfWorthLevel, builder: (column) => column);
Expression<T> entryActivitiesRefs<T extends Object>(
Expression<T> Function($$EntryActivitiesTableAnnotationComposer a) f) {
final $$EntryActivitiesTableAnnotationComposer composer = $composerBuilder(
@@ -2137,6 +2367,10 @@ class $$MoodEntriesTableTableManager extends RootTableManager<
Value<int> moodLevel = const Value.absent(),
Value<String?> note = const Value.absent(),
Value<DateTime> createdAt = const Value.absent(),
Value<int?> sleepMinutes = const Value.absent(),
Value<int?> energyLevel = const Value.absent(),
Value<int?> positivityLevel = const Value.absent(),
Value<int?> selfWorthLevel = const Value.absent(),
}) =>
MoodEntriesCompanion(
id: id,
@@ -2144,6 +2378,10 @@ class $$MoodEntriesTableTableManager extends RootTableManager<
moodLevel: moodLevel,
note: note,
createdAt: createdAt,
sleepMinutes: sleepMinutes,
energyLevel: energyLevel,
positivityLevel: positivityLevel,
selfWorthLevel: selfWorthLevel,
),
createCompanionCallback: ({
Value<int> id = const Value.absent(),
@@ -2151,6 +2389,10 @@ class $$MoodEntriesTableTableManager extends RootTableManager<
required int moodLevel,
Value<String?> note = const Value.absent(),
Value<DateTime> createdAt = const Value.absent(),
Value<int?> sleepMinutes = const Value.absent(),
Value<int?> energyLevel = const Value.absent(),
Value<int?> positivityLevel = const Value.absent(),
Value<int?> selfWorthLevel = const Value.absent(),
}) =>
MoodEntriesCompanion.insert(
id: id,
@@ -2158,6 +2400,10 @@ class $$MoodEntriesTableTableManager extends RootTableManager<
moodLevel: moodLevel,
note: note,
createdAt: createdAt,
sleepMinutes: sleepMinutes,
energyLevel: energyLevel,
positivityLevel: positivityLevel,
selfWorthLevel: selfWorthLevel,
),
withReferenceMapper: (p0) => p0
.map((e) => (