Add floating quick-add button to person insights

This commit is contained in:
Rijad Zuzo
2026-02-22 20:50:48 +01:00
parent 030f685749
commit 7686d0f9cf
3 changed files with 69 additions and 0 deletions
+4
View File
@@ -25,6 +25,10 @@ the expected context add action.
- Updated dashboard interaction coverage: - Updated dashboard interaction coverage:
- `test/features/dashboard/dashboard_graph_interactions_test.dart` - `test/features/dashboard/dashboard_graph_interactions_test.dart`
- now asserts `Quick add` is present after opening `Person Insights`. - now asserts `Quick add` is present after opening `Person Insights`.
- Added visible floating `+` button on `Person Insights` for mobile-first
discoverability:
- opens a bottom sheet with the same quick actions as the header menu
- tooltip: `Add to person`
## Latest Milestone (2026-02-18): Duplicate Profile Merge + Share Deep-Link Polish ## Latest Milestone (2026-02-18): Duplicate Profile Merge + Share Deep-Link Polish
@@ -712,9 +712,20 @@ class _PersonInsightsPage extends ConsumerWidget {
final AsyncValue<SignalsFeed> signals = ref.watch( final AsyncValue<SignalsFeed> signals = ref.watch(
signalsControllerProvider, signalsControllerProvider,
); );
final LocalDataState? localValue = localData.asData?.value;
final PersonProfile? quickAddPerson = localValue == null
? null
: _findPersonById(localValue.people, personId);
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('Person Insights')), appBar: AppBar(title: const Text('Person Insights')),
floatingActionButton: quickAddPerson == null
? null
: FloatingActionButton(
tooltip: 'Add to person',
onPressed: () => _openQuickAddSheet(context, ref, quickAddPerson),
child: const Icon(Icons.add_rounded),
),
body: localData.when( body: localData.when(
data: (LocalDataState data) { data: (LocalDataState data) {
final PersonProfile? person = _findPersonById(data.people, personId); final PersonProfile? person = _findPersonById(data.people, personId);
@@ -1143,6 +1154,59 @@ class _PersonInsightsPage extends ConsumerWidget {
} }
} }
Future<void> _openQuickAddSheet(
BuildContext context,
WidgetRef ref,
PersonProfile person,
) async {
final _InsightQuickAction? selected =
await showModalBottomSheet<_InsightQuickAction>(
context: context,
showDragHandle: true,
builder: (BuildContext context) {
return SafeArea(
child: ListView(
shrinkWrap: true,
children: <Widget>[
ListTile(
leading: const Icon(Icons.auto_awesome_rounded),
title: const Text('Add Capture'),
subtitle: const Text('Log a new moment or interaction'),
onTap: () =>
Navigator.of(context).pop(_InsightQuickAction.capture),
),
ListTile(
leading: const Icon(Icons.note_add_outlined),
title: const Text('Add Note'),
subtitle: const Text('Save a context note for later'),
onTap: () =>
Navigator.of(context).pop(_InsightQuickAction.note),
),
ListTile(
leading: const Icon(Icons.lightbulb_outline_rounded),
title: const Text('Add Idea'),
subtitle: const Text('Gift or event idea'),
onTap: () =>
Navigator.of(context).pop(_InsightQuickAction.idea),
),
ListTile(
leading: const Icon(Icons.notifications_active_outlined),
title: const Text('Add Reminder'),
subtitle: const Text('Schedule a follow-up prompt'),
onTap: () =>
Navigator.of(context).pop(_InsightQuickAction.reminder),
),
],
),
);
},
);
if (selected == null || !context.mounted) {
return;
}
await _handleQuickAction(context, ref, person, selected);
}
Future<String?> _showQuickTextCaptureDialog( Future<String?> _showQuickTextCaptureDialog(
BuildContext context, { BuildContext context, {
required String title, required String title,
@@ -42,6 +42,7 @@ void main() {
expect(find.text('Person Insights'), findsOneWidget); expect(find.text('Person Insights'), findsOneWidget);
expect(find.byTooltip('Quick add'), findsOneWidget); expect(find.byTooltip('Quick add'), findsOneWidget);
expect(find.byTooltip('Add to person'), findsOneWidget);
expect(find.text('Promotions & Signals'), findsOneWidget); expect(find.text('Promotions & Signals'), findsOneWidget);
expect(find.text('Ideas'), findsOneWidget); expect(find.text('Ideas'), findsOneWidget);
expect(find.text('Moments'), findsOneWidget); expect(find.text('Moments'), findsOneWidget);