234 lines
8.9 KiB
Dart
234 lines
8.9 KiB
Dart
// ignore_for_file: sort_constructors_first
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:relationship_saver/features/ai_digest/domain/ai_digest_models.dart';
|
|
import 'package:relationship_saver/features/dashboard/domain/dashboard_models.dart';
|
|
import 'package:relationship_saver/features/ideas/domain/idea_models.dart';
|
|
import 'package:relationship_saver/features/moments/domain/moment_models.dart';
|
|
import 'package:relationship_saver/features/people/domain/person_models.dart';
|
|
import 'package:relationship_saver/features/reminders/domain/reminder_models.dart';
|
|
import 'package:relationship_saver/features/share_intake/domain/share_models.dart';
|
|
|
|
/// Aggregate local snapshot used by the prototype app store.
|
|
///
|
|
/// During this prototyping phase the app still uses one persisted snapshot for
|
|
/// most product state. The types inside it are now feature-owned, so each slice
|
|
/// can evolve without hiding its models in a horizontal "local" module.
|
|
@immutable
|
|
class LocalDataState {
|
|
const LocalDataState({
|
|
required this.people,
|
|
required this.moments,
|
|
required this.ideas,
|
|
required this.reminders,
|
|
required this.tasks,
|
|
this.dismissedSignalIds = const <String>[],
|
|
this.sourceLinks = const <SourceProfileLink>[],
|
|
this.sharedMessages = const <SharedMessageEntry>[],
|
|
this.sharedInbox = const <SharedInboxEntry>[],
|
|
this.personFacts = const <PersonFact>[],
|
|
this.importantDates = const <PersonImportantDate>[],
|
|
this.preferenceSignals = const <PersonPreferenceSignal>[],
|
|
this.aiSuggestionDrafts = const <AiSuggestionDraft>[],
|
|
});
|
|
|
|
final List<PersonProfile> people;
|
|
final List<RelationshipMoment> moments;
|
|
final List<RelationshipIdea> ideas;
|
|
final List<ReminderRule> reminders;
|
|
final List<DashboardTask> tasks;
|
|
final List<String> dismissedSignalIds;
|
|
final List<SourceProfileLink> sourceLinks;
|
|
final List<SharedMessageEntry> sharedMessages;
|
|
final List<SharedInboxEntry> sharedInbox;
|
|
final List<PersonFact> personFacts;
|
|
final List<PersonImportantDate> importantDates;
|
|
final List<PersonPreferenceSignal> preferenceSignals;
|
|
final List<AiSuggestionDraft> aiSuggestionDrafts;
|
|
|
|
LocalDataState copyWith({
|
|
List<PersonProfile>? people,
|
|
List<RelationshipMoment>? moments,
|
|
List<RelationshipIdea>? ideas,
|
|
List<ReminderRule>? reminders,
|
|
List<DashboardTask>? tasks,
|
|
List<String>? dismissedSignalIds,
|
|
List<SourceProfileLink>? sourceLinks,
|
|
List<SharedMessageEntry>? sharedMessages,
|
|
List<SharedInboxEntry>? sharedInbox,
|
|
List<PersonFact>? personFacts,
|
|
List<PersonImportantDate>? importantDates,
|
|
List<PersonPreferenceSignal>? preferenceSignals,
|
|
List<AiSuggestionDraft>? aiSuggestionDrafts,
|
|
}) {
|
|
return LocalDataState(
|
|
people: people ?? this.people,
|
|
moments: moments ?? this.moments,
|
|
ideas: ideas ?? this.ideas,
|
|
reminders: reminders ?? this.reminders,
|
|
tasks: tasks ?? this.tasks,
|
|
dismissedSignalIds: dismissedSignalIds ?? this.dismissedSignalIds,
|
|
sourceLinks: sourceLinks ?? this.sourceLinks,
|
|
sharedMessages: sharedMessages ?? this.sharedMessages,
|
|
sharedInbox: sharedInbox ?? this.sharedInbox,
|
|
personFacts: personFacts ?? this.personFacts,
|
|
importantDates: importantDates ?? this.importantDates,
|
|
preferenceSignals: preferenceSignals ?? this.preferenceSignals,
|
|
aiSuggestionDrafts: aiSuggestionDrafts ?? this.aiSuggestionDrafts,
|
|
);
|
|
}
|
|
|
|
DashboardSummary summary({DateTime? now}) {
|
|
final DateTime baseline = now ?? DateTime.now();
|
|
return DashboardSummary(
|
|
activePeople: people.length,
|
|
upcomingPlans: people
|
|
.where((PersonProfile p) => p.nextMoment.isAfter(baseline))
|
|
.length,
|
|
pendingIdeas: ideas
|
|
.where((RelationshipIdea idea) => !idea.isArchived)
|
|
.length,
|
|
weeklyConsistency: moments.isEmpty
|
|
? 0
|
|
: (70 + moments.length * 4).clamp(0, 100),
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toJson() {
|
|
return <String, dynamic>{
|
|
'people': people
|
|
.map((PersonProfile person) => person.toJson())
|
|
.toList(growable: false),
|
|
'moments': moments
|
|
.map((RelationshipMoment moment) => moment.toJson())
|
|
.toList(growable: false),
|
|
'ideas': ideas
|
|
.map((RelationshipIdea idea) => idea.toJson())
|
|
.toList(growable: false),
|
|
'reminders': reminders
|
|
.map((ReminderRule reminder) => reminder.toJson())
|
|
.toList(growable: false),
|
|
'tasks': tasks
|
|
.map((DashboardTask task) => task.toJson())
|
|
.toList(growable: false),
|
|
'dismissedSignalIds': dismissedSignalIds,
|
|
'sourceLinks': sourceLinks
|
|
.map((SourceProfileLink link) => link.toJson())
|
|
.toList(growable: false),
|
|
'sharedMessages': sharedMessages
|
|
.map((SharedMessageEntry entry) => entry.toJson())
|
|
.toList(growable: false),
|
|
'sharedInbox': sharedInbox
|
|
.map((SharedInboxEntry entry) => entry.toJson())
|
|
.toList(growable: false),
|
|
'personFacts': personFacts
|
|
.map((PersonFact fact) => fact.toJson())
|
|
.toList(growable: false),
|
|
'importantDates': importantDates
|
|
.map((PersonImportantDate value) => value.toJson())
|
|
.toList(growable: false),
|
|
'preferenceSignals': preferenceSignals
|
|
.map((PersonPreferenceSignal signal) => signal.toJson())
|
|
.toList(growable: false),
|
|
'aiSuggestionDrafts': aiSuggestionDrafts
|
|
.map((AiSuggestionDraft draft) => draft.toJson())
|
|
.toList(growable: false),
|
|
};
|
|
}
|
|
|
|
factory LocalDataState.fromJson(Map<String, dynamic> json) {
|
|
return LocalDataState(
|
|
people: (json['people'] as List<dynamic>? ?? <dynamic>[])
|
|
.map(
|
|
(dynamic person) =>
|
|
PersonProfile.fromJson(person as Map<String, dynamic>),
|
|
)
|
|
.toList(growable: false),
|
|
moments: (json['moments'] as List<dynamic>? ?? <dynamic>[])
|
|
.map(
|
|
(dynamic moment) =>
|
|
RelationshipMoment.fromJson(moment as Map<String, dynamic>),
|
|
)
|
|
.toList(growable: false),
|
|
ideas: (json['ideas'] as List<dynamic>? ?? <dynamic>[])
|
|
.map(
|
|
(dynamic idea) =>
|
|
RelationshipIdea.fromJson(idea as Map<String, dynamic>),
|
|
)
|
|
.toList(growable: false),
|
|
reminders: (json['reminders'] as List<dynamic>? ?? <dynamic>[])
|
|
.map(
|
|
(dynamic reminder) =>
|
|
ReminderRule.fromJson(reminder as Map<String, dynamic>),
|
|
)
|
|
.toList(growable: false),
|
|
tasks: (json['tasks'] as List<dynamic>? ?? <dynamic>[])
|
|
.map(
|
|
(dynamic task) =>
|
|
DashboardTask.fromJson(task as Map<String, dynamic>),
|
|
)
|
|
.toList(growable: false),
|
|
dismissedSignalIds:
|
|
(json['dismissedSignalIds'] as List<dynamic>? ?? <dynamic>[])
|
|
.map((dynamic value) => '$value')
|
|
.toList(growable: false),
|
|
sourceLinks: (json['sourceLinks'] as List<dynamic>? ?? <dynamic>[])
|
|
.map(
|
|
(dynamic link) =>
|
|
SourceProfileLink.fromJson(link as Map<String, dynamic>),
|
|
)
|
|
.toList(growable: false),
|
|
sharedMessages: (json['sharedMessages'] as List<dynamic>? ?? <dynamic>[])
|
|
.map(
|
|
(dynamic entry) =>
|
|
SharedMessageEntry.fromJson(entry as Map<String, dynamic>),
|
|
)
|
|
.toList(growable: false),
|
|
sharedInbox: (json['sharedInbox'] as List<dynamic>? ?? <dynamic>[])
|
|
.map(
|
|
(dynamic entry) =>
|
|
SharedInboxEntry.fromJson(entry as Map<String, dynamic>),
|
|
)
|
|
.toList(growable: false),
|
|
personFacts: (json['personFacts'] as List<dynamic>? ?? <dynamic>[])
|
|
.map(
|
|
(dynamic fact) => PersonFact.fromJson(fact as Map<String, dynamic>),
|
|
)
|
|
.toList(growable: false),
|
|
importantDates: (json['importantDates'] as List<dynamic>? ?? <dynamic>[])
|
|
.map(
|
|
(dynamic value) =>
|
|
PersonImportantDate.fromJson(value as Map<String, dynamic>),
|
|
)
|
|
.toList(growable: false),
|
|
preferenceSignals:
|
|
(json['preferenceSignals'] as List<dynamic>? ?? <dynamic>[])
|
|
.map(
|
|
(dynamic signal) => PersonPreferenceSignal.fromJson(
|
|
signal as Map<String, dynamic>,
|
|
),
|
|
)
|
|
.toList(growable: false),
|
|
aiSuggestionDrafts:
|
|
(json['aiSuggestionDrafts'] as List<dynamic>? ?? <dynamic>[])
|
|
.map(
|
|
(dynamic draft) =>
|
|
AiSuggestionDraft.fromJson(draft as Map<String, dynamic>),
|
|
)
|
|
.toList(growable: false),
|
|
);
|
|
}
|
|
|
|
static LocalDataState empty() {
|
|
return const LocalDataState(
|
|
people: <PersonProfile>[],
|
|
moments: <RelationshipMoment>[],
|
|
ideas: <RelationshipIdea>[],
|
|
reminders: <ReminderRule>[],
|
|
tasks: <DashboardTask>[],
|
|
);
|
|
}
|
|
|
|
static LocalDataState seed() => empty();
|
|
}
|