-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #69 from pvdthings/search-by-item-number
Librarian - Search by item number
- Loading branch information
Showing
9 changed files
with
272 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
apps/librarian/lib/modules/things/providers/item_details_orchestrator.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:librarian_app/core/api/models/item_model.dart'; | ||
import 'package:librarian_app/dashboard/providers/end_drawer_provider.dart'; | ||
import 'package:librarian_app/utils/media_query.dart'; | ||
|
||
import '../details/inventory/item_details/drawer.dart'; | ||
import '../details/inventory/item_details/item_details_controller.dart'; | ||
import '../details/inventory/item_details_page.dart'; | ||
import 'things_repository_provider.dart'; | ||
|
||
class ItemDetailsOrchestrator { | ||
ItemDetailsOrchestrator(this.ref); | ||
|
||
final Ref ref; | ||
|
||
void openItem( | ||
BuildContext context, { | ||
required ItemModel item, | ||
required bool hiddenLocked, | ||
}) { | ||
if (isMobile(context)) { | ||
Navigator.of(context).push(MaterialPageRoute(builder: (context) { | ||
return ItemDetailsPage( | ||
item: item, | ||
hiddenLocked: hiddenLocked, | ||
); | ||
})); | ||
return; | ||
} | ||
|
||
final detailsController = ItemDetailsController( | ||
item: item, | ||
repository: ref.read(thingsRepositoryProvider.notifier), | ||
onSave: () { | ||
// setState(() => _isLoading = true); | ||
}, | ||
onSaveComplete: () { | ||
// setState(() => _isLoading = false); | ||
}, | ||
); | ||
|
||
ref.read(endDrawerProvider).openEndDrawer( | ||
context, | ||
ItemDetailsDrawer( | ||
controller: detailsController, | ||
isHiddenLocked: hiddenLocked, | ||
), | ||
); | ||
} | ||
} | ||
|
||
final itemDetailsOrchestrator = Provider((ref) => ItemDetailsOrchestrator(ref)); |
141 changes: 141 additions & 0 deletions
141
apps/librarian/lib/modules/things/search/item_lookup_button.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter/services.dart'; | ||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:librarian_app/core/api/models/item_model.dart'; | ||
import 'package:librarian_app/core/api/models/thing_model.dart'; | ||
import 'package:librarian_app/modules/things/providers/find_things.dart'; | ||
import 'package:librarian_app/modules/things/providers/item_details_orchestrator.dart'; | ||
import 'package:librarian_app/modules/things/providers/selected_thing_provider.dart'; | ||
import 'package:librarian_app/modules/things/providers/things_repository_provider.dart'; | ||
import 'package:librarian_app/widgets/input_decoration.dart'; | ||
|
||
class ItemLookupButton extends ConsumerWidget { | ||
const ItemLookupButton({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context, WidgetRef ref) { | ||
return IconButton( | ||
onPressed: () async { | ||
final result = await showDialog<LookupResult?>( | ||
context: context, | ||
builder: (context) => const ItemLookupDialog(), | ||
); | ||
|
||
// Load Thing and Item Details | ||
if (result != null) { | ||
ref.read(selectedThingProvider.notifier).state = result.thing; | ||
|
||
Future.delayed(Duration.zero, () { | ||
ref.read(itemDetailsOrchestrator).openItem(context, | ||
item: result.item, hiddenLocked: result.thing.hidden); | ||
}); | ||
} | ||
}, | ||
icon: const Icon(Icons.numbers), | ||
); | ||
} | ||
} | ||
|
||
class ItemLookupDialog extends ConsumerStatefulWidget { | ||
const ItemLookupDialog({super.key}); | ||
|
||
@override | ||
ConsumerState<ConsumerStatefulWidget> createState() { | ||
return _ItemLookupDialogState(); | ||
} | ||
} | ||
|
||
class _ItemLookupDialogState extends ConsumerState<ItemLookupDialog> { | ||
final formKey = GlobalKey<FormState>(); | ||
final numberController = TextEditingController(); | ||
|
||
String? errorMessage; | ||
|
||
void onSubmit() { | ||
if (formKey.currentState!.validate()) { | ||
search(int.parse(numberController.text)); | ||
} | ||
} | ||
|
||
void search(int number) async { | ||
final item = await ref | ||
.read(thingsRepositoryProvider.notifier) | ||
.getItem(number: number); | ||
|
||
if (item == null) { | ||
setState(() { | ||
errorMessage = 'Item #$number does not exist'; | ||
}); | ||
return; | ||
} | ||
|
||
final things = await ref.read(findThingsByItem(number: number)); | ||
final thing = things[0]; | ||
|
||
await Future.delayed(Duration.zero, () { | ||
Navigator.of(context).pop(LookupResult(item: item, thing: thing)); | ||
}); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return AlertDialog( | ||
icon: const Icon(Icons.search), | ||
title: const Text('Item Lookup'), | ||
actions: [ | ||
OutlinedButton( | ||
onPressed: () { | ||
Navigator.of(context).pop(null); | ||
}, | ||
child: const Text('Cancel'), | ||
), | ||
ValueListenableBuilder( | ||
valueListenable: numberController, | ||
builder: (context, name, child) => FilledButton( | ||
onPressed: name.text.isNotEmpty ? onSubmit : null, | ||
child: const Text('Look up'), | ||
), | ||
), | ||
], | ||
contentPadding: const EdgeInsets.all(16), | ||
content: SizedBox( | ||
width: 500, | ||
child: Form( | ||
key: formKey, | ||
autovalidateMode: AutovalidateMode.onUserInteraction, | ||
child: TextFormField( | ||
autofocus: true, | ||
controller: numberController, | ||
validator: (value) { | ||
if (value == null || value.isEmpty) { | ||
return 'Number is required'; | ||
} | ||
|
||
return null; | ||
}, | ||
onChanged: (value) { | ||
if (value.length < 3) { | ||
return; | ||
} | ||
}, | ||
onFieldSubmitted: (value) => onSubmit(), | ||
inputFormatters: [FilteringTextInputFormatter.digitsOnly], | ||
decoration: inputDecoration.copyWith( | ||
labelText: 'Item Number', | ||
constraints: const BoxConstraints(minWidth: 500), | ||
prefixIcon: const Icon(Icons.numbers), | ||
errorText: errorMessage, | ||
), | ||
), | ||
), | ||
), | ||
); | ||
} | ||
} | ||
|
||
class LookupResult { | ||
final ItemModel item; | ||
final ThingModel thing; | ||
|
||
LookupResult({required this.item, required this.thing}); | ||
} |
29 changes: 29 additions & 0 deletions
29
apps/librarian/lib/modules/things/search/search_field.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:librarian_app/widgets/fields/search_field.dart'; | ||
|
||
import '../providers/selected_thing_provider.dart'; | ||
import '../providers/things_filter_provider.dart'; | ||
import 'item_lookup_button.dart'; | ||
|
||
class ThingsSearchField extends ConsumerWidget { | ||
const ThingsSearchField({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context, WidgetRef ref) { | ||
return SearchField( | ||
text: ref.watch(thingsFilterProvider), | ||
onChanged: (value) { | ||
ref.read(thingsFilterProvider.notifier).state = value; | ||
}, | ||
onClearPressed: () { | ||
ref.read(thingsFilterProvider.notifier).state = null; | ||
ref.read(selectedThingProvider.notifier).state = null; | ||
}, | ||
trailing: const Tooltip( | ||
message: 'Item Lookup', | ||
child: ItemLookupButton(), | ||
), | ||
); | ||
} | ||
} |
Oops, something went wrong.