Skip to content

Commit

Permalink
feat: Basic details: explanations about the producer are in a b… (#5870)
Browse files Browse the repository at this point in the history
* Basic details: producer explanation is now on a banner

* Tiny fix
  • Loading branch information
g123k authored Nov 18, 2024
1 parent d7836ba commit c102a0e
Show file tree
Hide file tree
Showing 5 changed files with 249 additions and 145 deletions.
291 changes: 149 additions & 142 deletions packages/smooth_app/lib/pages/product/add_basic_details_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,18 @@ class _AddBasicDetailsPageState extends State<AddBasicDetailsPage> {

@override
Widget build(BuildContext context) {
final Size size = MediaQuery.sizeOf(context);
final AppLocalizations appLocalizations = AppLocalizations.of(context);

Widget child = _buildForm(appLocalizations, context);
if (_hasOwnerField()) {
child = Column(
children: <Widget>[
Expanded(child: child),
const OwnerFieldBanner(),
],
);
}

return WillPopScope2(
onWillPop: () async => (await _mayExitPage(saving: false), null),
child: UnfocusFieldWhenTapOutside(
Expand All @@ -102,161 +112,158 @@ class _AddBasicDetailsPageState extends State<AddBasicDetailsPage> {
title: appLocalizations.basic_details,
product: _product,
),
body: Form(
key: _formKey,
child: Scrollbar(
child: ListView(
body: child,
bottomNavigationBar: ProductBottomButtonsBar(
onSave: () async => _exitPage(
await _mayExitPage(saving: true),
),
onCancel: () async => _exitPage(
await _mayExitPage(saving: false),
),
),
),
),
);
}

Form _buildForm(AppLocalizations appLocalizations, BuildContext context) {
final Size size = MediaQuery.sizeOf(context);

return Form(
key: _formKey,
child: Scrollbar(
child: ListView(
children: <Widget>[
Align(
alignment: AlignmentDirectional.topStart,
child: ProductImageCarousel(
_product,
height: size.height * 0.20,
),
),
SizedBox(height: _heightSpace),
Padding(
padding: EdgeInsets.symmetric(
horizontal: size.width * 0.05,
),
child: Column(
children: <Widget>[
Align(
alignment: AlignmentDirectional.topStart,
child: ProductImageCarousel(
_product,
height: size.height * 0.20,
),
Text(
appLocalizations.barcode_barcode(_product.barcode!),
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
SizedBox(height: _heightSpace),
Padding(
padding: EdgeInsets.symmetric(
horizontal: size.width * 0.05,
),
child: Column(
children: <Widget>[
Text(
appLocalizations.barcode_barcode(_product.barcode!),
style:
Theme.of(context).textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.bold,
ConsumerFilter<UserPreferences>(
buildWhen: (
UserPreferences? previousValue,
UserPreferences currentValue,
) {
return previousValue?.getFlag(UserPreferencesDevMode
.userPreferencesFlagSpellCheckerOnOcr) !=
currentValue.getFlag(UserPreferencesDevMode
.userPreferencesFlagSpellCheckerOnOcr);
},
builder: (BuildContext context, UserPreferences prefs,
Widget? child) {
if (_multilingualHelper.isMonolingual()) {
return SmoothTextFormField(
suffixIcon: _getOwnerFieldIcon(
ProductField.NAME,
),
controller: _productNameController,
type: TextFieldTypes.PLAIN_TEXT,
hintText: appLocalizations.product_name,
spellCheckConfiguration: (prefs.getFlag(
UserPreferencesDevMode
.userPreferencesFlagSpellCheckerOnOcr) ??
false) &&
(Platform.isAndroid || Platform.isIOS)
? const SpellCheckConfiguration()
: const SpellCheckConfiguration.disabled(),
);
} else {
return Card(
child: Column(
children: <Widget>[
_multilingualHelper.getLanguageSelector(
setState: setState,
product: _product,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: SmoothTextFormField(
suffixIcon: _getOwnerFieldIcon(
ProductField.NAME_IN_LANGUAGES,
language: _multilingualHelper
.getCurrentLanguage(),
),
),
SizedBox(height: _heightSpace),
ConsumerFilter<UserPreferences>(
buildWhen: (
UserPreferences? previousValue,
UserPreferences currentValue,
) {
return previousValue?.getFlag(UserPreferencesDevMode
.userPreferencesFlagSpellCheckerOnOcr) !=
currentValue.getFlag(UserPreferencesDevMode
.userPreferencesFlagSpellCheckerOnOcr);
},
builder: (BuildContext context, UserPreferences prefs,
Widget? child) {
if (_multilingualHelper.isMonolingual()) {
return SmoothTextFormField(
suffixIcon: _getOwnerFieldIcon(
ProductField.NAME,
),
controller: _productNameController,
type: TextFieldTypes.PLAIN_TEXT,
hintText: appLocalizations.product_name,
spellCheckConfiguration: (prefs.getFlag(
UserPreferencesDevMode
.userPreferencesFlagSpellCheckerOnOcr) ??
false) &&
(Platform.isAndroid || Platform.isIOS)
? const SpellCheckConfiguration()
: const SpellCheckConfiguration.disabled(),
);
} else {
return Card(
child: Column(
children: <Widget>[
_multilingualHelper.getLanguageSelector(
setState: setState,
product: _product,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: SmoothTextFormField(
suffixIcon: _getOwnerFieldIcon(
ProductField.NAME_IN_LANGUAGES,
language: _multilingualHelper
.getCurrentLanguage(),
),
controller: _productNameController,
type: TextFieldTypes.PLAIN_TEXT,
hintText: appLocalizations.product_name,
spellCheckConfiguration: (prefs.getFlag(
UserPreferencesDevMode
.userPreferencesFlagSpellCheckerOnOcr) ??
false) &&
(Platform.isAndroid ||
Platform.isIOS)
? const SpellCheckConfiguration()
: const SpellCheckConfiguration
.disabled(),
),
),
],
),
);
}
},
),
SizedBox(height: _heightSpace),
LayoutBuilder(
builder: (
final BuildContext context,
final BoxConstraints constraints,
) =>
SmoothAutocompleteTextField(
focusNode: _focusNode,
controller: _brandNameController,
autocompleteKey: _autocompleteKey,
allowEmojis: false,
hintText: appLocalizations.brand_name,
constraints: constraints,
suffixIcon: _getOwnerFieldIcon(
ProductField.BRANDS,
),
manager: AutocompleteManager(
TaxonomyNameAutocompleter(
taxonomyNames: <TaxonomyName>[
TaxonomyName.brand
],
// for brands, language must be English
language: OpenFoodFactsLanguage.ENGLISH,
user: ProductQuery.getReadUser(),
limit: 25,
fuzziness: Fuzziness.none,
uriHelper: ProductQuery.getUriProductHelper(
productType: _product.productType,
controller: _productNameController,
type: TextFieldTypes.PLAIN_TEXT,
hintText: appLocalizations.product_name,
spellCheckConfiguration: (prefs.getFlag(
UserPreferencesDevMode
.userPreferencesFlagSpellCheckerOnOcr) ??
false) &&
(Platform.isAndroid || Platform.isIOS)
? const SpellCheckConfiguration()
: const SpellCheckConfiguration
.disabled(),
),
),
),
],
),
),
SizedBox(height: _heightSpace),
SmoothTextFormField(
suffixIcon: _getOwnerFieldIcon(
ProductField.QUANTITY,
);
}
},
),
SizedBox(height: _heightSpace),
LayoutBuilder(
builder: (
final BuildContext context,
final BoxConstraints constraints,
) =>
SmoothAutocompleteTextField(
focusNode: _focusNode,
controller: _brandNameController,
autocompleteKey: _autocompleteKey,
allowEmojis: false,
hintText: appLocalizations.brand_name,
constraints: constraints,
suffixIcon: _getOwnerFieldIcon(
ProductField.BRANDS,
),
manager: AutocompleteManager(
TaxonomyNameAutocompleter(
taxonomyNames: <TaxonomyName>[TaxonomyName.brand],
// for brands, language must be English
language: OpenFoodFactsLanguage.ENGLISH,
user: ProductQuery.getReadUser(),
limit: 25,
fuzziness: Fuzziness.none,
uriHelper: ProductQuery.getUriProductHelper(
productType: _product.productType,
),
controller: _weightController,
type: TextFieldTypes.PLAIN_TEXT,
hintText: appLocalizations.quantity,
),
if (_hasOwnerField())
const Padding(
padding: EdgeInsets.only(top: LARGE_SPACE),
child: Card(child: OwnerFieldInfo()),
),
// in order to be able to scroll suggestions
const SizedBox(height: 150),
],
),
),
),
SizedBox(height: _heightSpace),
SmoothTextFormField(
suffixIcon: _getOwnerFieldIcon(
ProductField.QUANTITY,
),
controller: _weightController,
type: TextFieldTypes.PLAIN_TEXT,
hintText: appLocalizations.quantity,
),
// in order to be able to scroll suggestions
const SizedBox(height: 150),
],
),
),
),
bottomNavigationBar: ProductBottomButtonsBar(
onSave: () async => _exitPage(
await _mayExitPage(saving: true),
),
onCancel: () async => _exitPage(
await _mayExitPage(saving: false),
),
),
],
),
),
);
Expand Down
16 changes: 16 additions & 0 deletions packages/smooth_app/lib/pages/product/owner_field_info.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:smooth_app/widgets/smooth_banner.dart';

/// Icon to display when the product field value is "producer provided".
const IconData _ownerFieldIconData = Icons.factory;
Expand All @@ -23,6 +24,21 @@ class OwnerFieldInfo extends StatelessWidget {
}
}

class OwnerFieldBanner extends StatelessWidget {
const OwnerFieldBanner({super.key});

@override
Widget build(BuildContext context) {
final AppLocalizations appLocalizations = AppLocalizations.of(context);

return SmoothBanner(
icon: const OwnerFieldIcon(),
title: appLocalizations.owner_field_info_title,
content: appLocalizations.owner_field_info_message,
);
}
}

/// Standard icon about "owner fields".
class OwnerFieldIcon extends StatelessWidget {
const OwnerFieldIcon();
Expand Down
2 changes: 1 addition & 1 deletion packages/smooth_app/lib/themes/smooth_theme_colors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class SmoothColorsThemeExtension
});

SmoothColorsThemeExtension.defaultValues()
: primaryUltraBlack = const Color(0xFF52443D),
: primaryUltraBlack = const Color(0xFF201A17),
primaryBlack = const Color(0xFF341100),
primaryDark = const Color(0xFF483527),
primarySemiDark = const Color(0xFF52443D),
Expand Down
Loading

0 comments on commit c102a0e

Please sign in to comment.