From a001634458d63f635ab5d2cc5ca768c9bd68d0f0 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Mon, 18 Nov 2024 10:08:59 -0500 Subject: [PATCH 1/2] use text field error text for unavailable and unknown items --- .../items/connected_thing_search_field.dart | 95 +++++++------------ 1 file changed, 34 insertions(+), 61 deletions(-) diff --git a/apps/librarian/lib/modules/loans/checkout/stepper/items/connected_thing_search_field.dart b/apps/librarian/lib/modules/loans/checkout/stepper/items/connected_thing_search_field.dart index d8ce017..7575c14 100644 --- a/apps/librarian/lib/modules/loans/checkout/stepper/items/connected_thing_search_field.dart +++ b/apps/librarian/lib/modules/loans/checkout/stepper/items/connected_thing_search_field.dart @@ -26,32 +26,39 @@ class ConnectedThingSearchField extends StatelessWidget { @override Widget build(BuildContext context) { - return TextField( - controller: _textController, - onSubmitted: (_) => _submit(), - decoration: InputDecoration( - hintText: 'Enter Item Number', - prefixIcon: const Icon(Icons.numbers), - suffixIcon: IconButton( - tooltip: 'Add Item', - onPressed: () => _submit(), - icon: const Icon(Icons.add_rounded), - ), - ), - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly, - ], - ); + return ListenableBuilder( + listenable: controller, + builder: (context, child) { + return TextField( + controller: _textController, + onSubmitted: (_) => _submit(), + decoration: InputDecoration( + errorText: controller.errorText, + hintText: 'Enter Item Number', + prefixIcon: const Icon(Icons.numbers), + suffixIcon: IconButton( + tooltip: 'Add Item', + onPressed: () => _submit(), + icon: const Icon(Icons.add_rounded), + ), + ), + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + ], + ); + }); } } -class ThingSearchController { +class ThingSearchController extends ChangeNotifier { final BuildContext context; final InventoryRepository repository; final void Function(ItemModel) onMatchFound; bool isLoading = false; + String? errorText; + ThingSearchController({ required this.context, required this.repository, @@ -63,51 +70,17 @@ class ThingSearchController { final match = await repository.getItem(number: int.parse(value)); isLoading = false; - if (match != null) { - if (!match.available) { - _showThingCheckedOutDialog(match); - } else { - onMatchFound(match); - } - } else { - _showUnknownThingDialog(value); + if (match == null) { + errorText = '#$value could not be found.'; + notifyListeners(); + return; } - } - void _showThingCheckedOutDialog(ItemModel thing) { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: const Text("Item Unavailable"), - content: Text( - "Item #${thing.number} is checked out or not available for lending."), - actions: [ - TextButton( - child: const Text("OK"), - onPressed: () => Navigator.pop(context), - ) - ], - ); - }, - ); - } - - void _showUnknownThingDialog(String searchValue) { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: Text("Item #$searchValue does not exist."), - content: const Text("Try another number."), - actions: [ - TextButton( - child: const Text("OK"), - onPressed: () => Navigator.pop(context), - ) - ], - ); - }, - ); + if (!match.available) { + errorText = '#$value is unavailable.'; + notifyListeners(); + } else { + onMatchFound(match); + } } } From 7bec2c097c8d62c13f18d871082edcddbb98e5f9 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Mon, 18 Nov 2024 10:26:02 -0500 Subject: [PATCH 2/2] use error text instead of existing item dialog --- .../items/connected_thing_search_field.dart | 17 ++++++++++--- .../stepper/items/existing_item_dialog.dart | 23 ------------------ .../checkout/stepper/items/items_step.dart | 24 ++++++------------- 3 files changed, 21 insertions(+), 43 deletions(-) delete mode 100644 apps/librarian/lib/modules/loans/checkout/stepper/items/existing_item_dialog.dart diff --git a/apps/librarian/lib/modules/loans/checkout/stepper/items/connected_thing_search_field.dart b/apps/librarian/lib/modules/loans/checkout/stepper/items/connected_thing_search_field.dart index 7575c14..5f2e230 100644 --- a/apps/librarian/lib/modules/loans/checkout/stepper/items/connected_thing_search_field.dart +++ b/apps/librarian/lib/modules/loans/checkout/stepper/items/connected_thing_search_field.dart @@ -52,6 +52,7 @@ class ConnectedThingSearchField extends StatelessWidget { class ThingSearchController extends ChangeNotifier { final BuildContext context; + final List items; final InventoryRepository repository; final void Function(ItemModel) onMatchFound; @@ -61,13 +62,22 @@ class ThingSearchController extends ChangeNotifier { ThingSearchController({ required this.context, + required this.items, required this.repository, required this.onMatchFound, }); Future search(String value) async { + final itemNumber = int.parse(value); + + if (items.any((t) => t.number == itemNumber)) { + errorText = '#$value is already added to this loan.'; + notifyListeners(); + return; + } + isLoading = true; - final match = await repository.getItem(number: int.parse(value)); + final match = await repository.getItem(number: itemNumber); isLoading = false; if (match == null) { @@ -79,8 +89,9 @@ class ThingSearchController extends ChangeNotifier { if (!match.available) { errorText = '#$value is unavailable.'; notifyListeners(); - } else { - onMatchFound(match); + return; } + + onMatchFound(match); } } diff --git a/apps/librarian/lib/modules/loans/checkout/stepper/items/existing_item_dialog.dart b/apps/librarian/lib/modules/loans/checkout/stepper/items/existing_item_dialog.dart deleted file mode 100644 index e1d99ad..0000000 --- a/apps/librarian/lib/modules/loans/checkout/stepper/items/existing_item_dialog.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:flutter/material.dart'; - -class ExistingItemDialog extends StatelessWidget { - const ExistingItemDialog({super.key, required this.number}); - - final int number; - - @override - Widget build(BuildContext context) { - return AlertDialog( - title: Text('Item #$number Already Added'), - content: const Text("The item can't be added again."), - actions: [ - FilledButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('OK'), - ), - ], - ); - } -} diff --git a/apps/librarian/lib/modules/loans/checkout/stepper/items/items_step.dart b/apps/librarian/lib/modules/loans/checkout/stepper/items/items_step.dart index 8cd06ae..9715eb4 100644 --- a/apps/librarian/lib/modules/loans/checkout/stepper/items/items_step.dart +++ b/apps/librarian/lib/modules/loans/checkout/stepper/items/items_step.dart @@ -5,7 +5,6 @@ import 'package:librarian_app/modules/things/providers/things_repository_provide import 'package:librarian_app/widgets/item_card.dart'; import 'connected_thing_search_field.dart'; -import 'existing_item_dialog.dart'; import 'eye_protection_dialog.dart'; import 'suggested_things_dialog.dart'; @@ -27,20 +26,11 @@ Step buildItemsStep({ ConnectedThingSearchField( controller: ThingSearchController( context: context, - onMatchFound: (thing) { - if (items.any((t) => t.id == thing.id)) { - showDialog( - context: context, - builder: (context) { - return ExistingItemDialog(number: thing.number); - }, - ); - return; - } - - onAddItem(thing); + items: items, + onMatchFound: (item) { + onAddItem(item); - if (thing.eyeProtection && !didPromptForEyeProtection) { + if (item.eyeProtection && !didPromptForEyeProtection) { showDialog( context: context, builder: (_) => const EyeProtectionDialog(), @@ -48,12 +38,12 @@ Step buildItemsStep({ onPromptForEyeProtection(); } - if (thing.linkedThingIds.isNotEmpty) { + if (item.linkedThingIds.isNotEmpty) { showDialog( context: context, builder: (_) => SuggestedThingsDialog( - thingName: thing.name, - thingIds: thing.linkedThingIds, + thingName: item.name, + thingIds: item.linkedThingIds, ), ); }