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..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 @@ -26,88 +26,72 @@ 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 List items; final InventoryRepository repository; final void Function(ItemModel) onMatchFound; bool isLoading = false; + String? errorText; + 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) { - 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), - ) - ], - ); - }, - ); - } + if (!match.available) { + errorText = '#$value is unavailable.'; + notifyListeners(); + return; + } - 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), - ) - ], - ); - }, - ); + 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, ), ); }