diff --git a/apps/librarian/lib/modules/things/details/inventory/item_details/condition_dropdown.dart b/apps/librarian/lib/modules/things/details/inventory/item_details/condition_dropdown.dart new file mode 100644 index 0000000..b37ac2e --- /dev/null +++ b/apps/librarian/lib/modules/things/details/inventory/item_details/condition_dropdown.dart @@ -0,0 +1,86 @@ +import 'package:flutter/material.dart'; +import 'package:librarian_app/widgets/hint_text.dart'; + +class ConditionDropdown extends StatelessWidget { + const ConditionDropdown({ + super.key, + required this.editable, + required this.onChanged, + required this.value, + }); + + final bool editable; + final String? value; + final void Function(ConditionDropdownOption?) onChanged; + + static final options = [ + ConditionDropdownOption( + label: 'None', + value: null, + ), + ConditionDropdownOption( + label: 'Like New', + value: 'Like New', + ), + ConditionDropdownOption( + label: 'Lightly Used', + value: 'Lightly Used', + ), + ConditionDropdownOption( + label: 'Heavily Used', + value: 'Heavily Used', + ), + ConditionDropdownOption( + label: 'Damaged', + value: 'Damaged', + hidden: true, + ), + ConditionDropdownOption( + label: 'In Repair', + value: 'In Repair', + hidden: true, + ), + ]; + + static bool isDamagedCondition(String? value) { + return value == 'Damaged' || value == 'In Repair'; + } + + @override + Widget build(BuildContext context) { + return DropdownButtonFormField( + decoration: const InputDecoration( + labelText: 'Condition', + ), + items: editable + ? options + .map((option) => DropdownMenuItem( + value: option, + child: Row( + children: [ + Text(option.label), + const SizedBox(width: 16.0), + if (option.hidden != null && option.hidden!) + const HintText('Hidden'), + ], + ), + )) + .toList() + : null, + onChanged: onChanged, + value: options.firstWhere((i) => i.value == value), + ); + } +} + +class ConditionDropdownOption { + final String label; + final String? value; + final bool? hidden; + + ConditionDropdownOption({ + required this.label, + required this.value, + this.hidden, + }); +} diff --git a/apps/librarian/lib/modules/things/details/inventory/item_details/item_details.dart b/apps/librarian/lib/modules/things/details/inventory/item_details/item_details.dart index 4daaee5..607af1c 100644 --- a/apps/librarian/lib/modules/things/details/inventory/item_details/item_details.dart +++ b/apps/librarian/lib/modules/things/details/inventory/item_details/item_details.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:librarian_app/modules/things/details/inventory/item_details/condition_dropdown.dart'; import 'package:librarian_app/modules/things/details/inventory/item_details/item_details_controller.dart'; import 'package:librarian_app/modules/things/details/inventory/item_manuals_card.dart'; import 'package:librarian_app/modules/things/details/image/thing_image_card.dart'; @@ -21,6 +22,11 @@ class ItemDetails extends ConsumerWidget { final ItemModel item; final bool isThingHidden; + get _isItemDamaged { + final condition = controller.conditionNotifier.value; + return ConditionDropdown.isDamagedCondition(condition); + } + @override Widget build(BuildContext context, WidgetRef ref) { return ListenableBuilder( @@ -43,13 +49,35 @@ class ItemDetails extends ConsumerWidget { clipBehavior: Clip.antiAlias, elevation: isMobile(context) ? 1 : 0, margin: EdgeInsets.zero, - child: _HiddenCheckboxListTile( - isThingHidden: isThingHidden, - isManagedByPartner: item.isManagedByPartner, - value: controller.hiddenNotifier.value, - onChanged: (value) { - controller.hiddenNotifier.value = value ?? false; - }, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: ConditionDropdown( + editable: !controller.isLoading, + onChanged: (option) { + controller.conditionNotifier.value = option?.value; + + // Some conditions are also treated as "hidden" + if (option?.hidden == true) { + controller.hiddenNotifier.value = true; + } else { + controller.hiddenNotifier.value = item.hidden; + } + }, + value: controller.conditionNotifier.value, + ), + ), + _HiddenCheckboxListTile( + isItemDamaged: _isItemDamaged, + isThingHidden: isThingHidden, + isManagedByPartner: item.isManagedByPartner, + value: controller.hiddenNotifier.value, + onChanged: (value) { + controller.hiddenNotifier.value = value ?? false; + }, + ), + ], ), ), const SizedBox(height: 32), @@ -118,40 +146,6 @@ class ItemDetails extends ConsumerWidget { keyboardType: TextInputType.number, ), const SizedBox(height: 16), - DropdownButtonFormField( - decoration: const InputDecoration( - labelText: 'Condition', - ), - items: controller.isLoading - ? null - : const [ - DropdownMenuItem( - value: null, - child: Text('None'), - ), - DropdownMenuItem( - value: 'Like New', - child: Text('Like New'), - ), - DropdownMenuItem( - value: 'Lightly Used', - child: Text('Lightly Used'), - ), - DropdownMenuItem( - value: 'Heavily Used', - child: Text('Heavily Used'), - ), - DropdownMenuItem( - value: 'Damaged', - child: Text('Damaged'), - ), - ], - onChanged: (value) { - controller.conditionNotifier.value = value; - }, - value: controller.conditionNotifier.value, - ), - const SizedBox(height: 16), TextFormField( decoration: const InputDecoration( labelText: 'Location', @@ -185,12 +179,14 @@ class ItemDetails extends ConsumerWidget { class _HiddenCheckboxListTile extends StatelessWidget { const _HiddenCheckboxListTile({ + required this.isItemDamaged, required this.isThingHidden, required this.isManagedByPartner, required this.value, required this.onChanged, }); + final bool isItemDamaged; final bool isThingHidden; final bool isManagedByPartner; final bool? value; @@ -222,6 +218,17 @@ class _HiddenCheckboxListTile extends StatelessWidget { ); } + if (isItemDamaged) { + return const CheckboxListTile( + title: Text('Hidden'), + subtitle: Text( + 'Unable to unhide because this item is not in working condition.'), + secondary: Icon(Icons.visibility_off_outlined), + value: true, + onChanged: null, + ); + } + return CheckboxListTile( title: const Text('Hidden'), secondary: value == true diff --git a/apps/librarian/lib/widgets/hint_text.dart b/apps/librarian/lib/widgets/hint_text.dart index e846da1..e516763 100644 --- a/apps/librarian/lib/widgets/hint_text.dart +++ b/apps/librarian/lib/widgets/hint_text.dart @@ -9,8 +9,11 @@ class HintText extends StatelessWidget { Widget build(BuildContext context) { return Text( text, - style: - Theme.of(context).textTheme.bodyMedium?.copyWith(color: Colors.grey), + style: hintTextStyle(context), ); } } + +TextStyle? hintTextStyle(BuildContext context) { + return Theme.of(context).textTheme.bodyMedium?.copyWith(color: Colors.grey); +} diff --git a/apps/librarian/pubspec.yaml b/apps/librarian/pubspec.yaml index 1156e02..e3f48c2 100644 --- a/apps/librarian/pubspec.yaml +++ b/apps/librarian/pubspec.yaml @@ -10,7 +10,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # followed by an optional build number separated by a +. # Both the version and the builder number may be overridden in flutter # build by specifying --build-name and --build-number, respectively. -version: 1.0.0+16 +version: 1.0.0+17 environment: sdk: '>=3.0.0'