diff --git a/packages/smooth_app/lib/pages/prices/price_add_product_card.dart b/packages/smooth_app/lib/pages/prices/price_add_product_card.dart index 2d4c29c8682..1f64f56e43e 100644 --- a/packages/smooth_app/lib/pages/prices/price_add_product_card.dart +++ b/packages/smooth_app/lib/pages/prices/price_add_product_card.dart @@ -4,6 +4,7 @@ import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/generic_lib/buttons/smooth_large_button_with_icon.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_text_form_field.dart'; @@ -40,14 +41,15 @@ class _PriceAddProductCardState extends State { @override Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); - return SmoothCard( + return SmoothCardWithRoundedHeader( + title: appLocalizations.prices_add_an_item, + leading: const Icon(Icons.add_circle_outlined), + contentPadding: const EdgeInsetsDirectional.symmetric( + horizontal: SMALL_SPACE, + vertical: MEDIUM_SPACE, + ), child: Column( children: [ - ListTile( - title: Text( - appLocalizations.prices_add_an_item, - ), - ), SmoothLargeButtonWithIcon( text: appLocalizations.prices_barcode_reader_action, icon: Icons.barcode_reader, diff --git a/packages/smooth_app/lib/pages/prices/price_amount_card.dart b/packages/smooth_app/lib/pages/prices/price_amount_card.dart index 0a3b67465c7..24c12bbef54 100644 --- a/packages/smooth_app/lib/pages/prices/price_amount_card.dart +++ b/packages/smooth_app/lib/pages/prices/price_amount_card.dart @@ -51,13 +51,16 @@ class _PriceAmountCardState extends State { final PriceAmountModel model = priceModel.elementAt(widget.index); final int total = priceModel.length; - return SmoothCard( + return SmoothCardWithRoundedHeader( + title: '${appLocalizations.prices_amount_subtitle}' + '${total == 1 ? '' : ' (${widget.index + 1}/$total)'}', + leading: const Icon(Icons.calculate_rounded), + contentPadding: const EdgeInsetsDirectional.symmetric( + vertical: MEDIUM_SPACE, + horizontal: SMALL_SPACE, + ), child: Column( children: [ - Text( - '${appLocalizations.prices_amount_subtitle}' - '${total == 1 ? '' : ' (${widget.index + 1}/$total)'}', - ), PriceProductListTile( product: model.product, trailingIconData: total == 1 ? null : Icons.clear, diff --git a/packages/smooth_app/lib/pages/prices/price_currency_card.dart b/packages/smooth_app/lib/pages/prices/price_currency_card.dart index fb82c1bf94e..e711b9910a8 100644 --- a/packages/smooth_app/lib/pages/prices/price_currency_card.dart +++ b/packages/smooth_app/lib/pages/prices/price_currency_card.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/pages/prices/price_currency_selector.dart'; @@ -10,13 +11,14 @@ class PriceCurrencyCard extends StatelessWidget { @override Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); - return SmoothCard( - child: Column( - children: [ - Text(appLocalizations.prices_currency_subtitle), - PriceCurrencySelector(), - ], + return SmoothCardWithRoundedHeader( + title: appLocalizations.prices_currency_subtitle, + leading: const Icon(Icons.price_change), + contentPadding: const EdgeInsetsDirectional.symmetric( + horizontal: SMALL_SPACE, + vertical: MEDIUM_SPACE, ), + child: PriceCurrencySelector(), ); } } diff --git a/packages/smooth_app/lib/pages/prices/price_date_card.dart b/packages/smooth_app/lib/pages/prices/price_date_card.dart index 4acce28ac87..df416c2bfb6 100644 --- a/packages/smooth_app/lib/pages/prices/price_date_card.dart +++ b/packages/smooth_app/lib/pages/prices/price_date_card.dart @@ -3,6 +3,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/generic_lib/buttons/smooth_large_button_with_icon.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/pages/prices/price_model.dart'; import 'package:smooth_app/query/product_query.dart'; @@ -17,42 +18,42 @@ class PriceDateCard extends StatelessWidget { final AppLocalizations appLocalizations = AppLocalizations.of(context); final String locale = ProductQuery.getLocaleString(); final DateFormat dateFormat = DateFormat.yMd(locale); - return SmoothCard( - child: Column( - children: [ - Text(appLocalizations.prices_date_subtitle), - SmoothLargeButtonWithIcon( - text: dateFormat.format(model.date), - icon: Icons.calendar_month, - onPressed: model.proof != null - ? null - : () async { - final DateTime? newDate = await showDatePicker( - context: context, - locale: Locale(ProductQuery.getLanguage().offTag), - firstDate: model.firstDate, - lastDate: model.today, - builder: - (final BuildContext context, final Widget? child) { - // for some reason we don't have a fine display without that theme. - // cf. https://stackoverflow.com/questions/50321182/how-to-customize-a-date-picker - final ThemeData themeData = - Theme.of(context).brightness == Brightness.light - ? ThemeData.light() - : ThemeData.dark(); - return Theme( - data: themeData.copyWith(), - child: child!, - ); - }, + return SmoothCardWithRoundedHeader( + title: appLocalizations.prices_date_subtitle, + leading: const Icon(Icons.calendar_month), + contentPadding: const EdgeInsetsDirectional.symmetric( + horizontal: SMALL_SPACE, + vertical: MEDIUM_SPACE, + ), + child: SmoothLargeButtonWithIcon( + text: dateFormat.format(model.date), + icon: Icons.calendar_month, + onPressed: model.proof != null + ? null + : () async { + final DateTime? newDate = await showDatePicker( + context: context, + locale: Locale(ProductQuery.getLanguage().offTag), + firstDate: model.firstDate, + lastDate: model.today, + builder: (final BuildContext context, final Widget? child) { + // for some reason we don't have a fine display without that theme. + // cf. https://stackoverflow.com/questions/50321182/how-to-customize-a-date-picker + final ThemeData themeData = + Theme.of(context).brightness == Brightness.light + ? ThemeData.light() + : ThemeData.dark(); + return Theme( + data: themeData.copyWith(), + child: child!, ); - if (newDate == null) { - return; - } - model.date = newDate; }, - ), - ], + ); + if (newDate == null) { + return; + } + model.date = newDate; + }, ), ); } diff --git a/packages/smooth_app/lib/pages/prices/price_location_card.dart b/packages/smooth_app/lib/pages/prices/price_location_card.dart index 05d5e17eba6..f2ef9c15b1a 100644 --- a/packages/smooth_app/lib/pages/prices/price_location_card.dart +++ b/packages/smooth_app/lib/pages/prices/price_location_card.dart @@ -4,6 +4,7 @@ import 'package:provider/provider.dart'; import 'package:smooth_app/database/dao_osm_location.dart'; import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/generic_lib/buttons/smooth_large_button_with_icon.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/pages/locations/osm_location.dart'; import 'package:smooth_app/pages/locations/search_location_helper.dart'; @@ -21,57 +22,58 @@ class PriceLocationCard extends StatelessWidget { final PriceModel model = context.watch(); final AppLocalizations appLocalizations = AppLocalizations.of(context); final OsmLocation? location = model.location; - return SmoothCard( - child: Column( - children: [ - Text(appLocalizations.prices_location_subtitle), - SmoothLargeButtonWithIcon( - text: location == null - ? appLocalizations.prices_location_find - : location.getTitle() ?? - location.getSubtitle() ?? - location.getLatLng().toString(), - icon: location == null - ? Icons.shopping_cart - : PriceButton.locationIconData, - onPressed: model.proof != null - ? null - : () async { - final LocalDatabase localDatabase = - context.read(); - final List preloadedList = - []; - for (final OsmLocation osmLocation in model.locations!) { - preloadedList.add( - SearchLocationPreloadedItem( - osmLocation, - popFirst: false, - ), - ); - } - final OsmLocation? osmLocation = - await Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) => SearchPage( - SearchLocationHelper(), - preloadedList: preloadedList, - autofocus: false, - ), - ), - ); - if (osmLocation == null) { - return; - } - final DaoOsmLocation daoOsmLocation = - DaoOsmLocation(localDatabase); - await daoOsmLocation.put(osmLocation); - final List newOsmLocations = - await daoOsmLocation.getAll(); - model.locations = newOsmLocations; - }, - ), - ], + return SmoothCardWithRoundedHeader( + title: appLocalizations.prices_location_subtitle, + leading: const Icon(Icons.shopping_cart), + contentPadding: const EdgeInsetsDirectional.symmetric( + horizontal: SMALL_SPACE, + vertical: MEDIUM_SPACE, + ), + child: SmoothLargeButtonWithIcon( + text: location == null + ? appLocalizations.prices_location_find + : location.getTitle() ?? + location.getSubtitle() ?? + location.getLatLng().toString(), + icon: location == null + ? Icons.shopping_cart + : PriceButton.locationIconData, + onPressed: model.proof != null + ? null + : () async { + final LocalDatabase localDatabase = + context.read(); + final List preloadedList = + []; + for (final OsmLocation osmLocation in model.locations!) { + preloadedList.add( + SearchLocationPreloadedItem( + osmLocation, + popFirst: false, + ), + ); + } + final OsmLocation? osmLocation = + await Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => SearchPage( + SearchLocationHelper(), + preloadedList: preloadedList, + autofocus: false, + ), + ), + ); + if (osmLocation == null) { + return; + } + final DaoOsmLocation daoOsmLocation = + DaoOsmLocation(localDatabase); + await daoOsmLocation.put(osmLocation); + final List newOsmLocations = + await daoOsmLocation.getAll(); + model.locations = newOsmLocations; + }, ), ); } diff --git a/packages/smooth_app/lib/pages/prices/price_proof_card.dart b/packages/smooth_app/lib/pages/prices/price_proof_card.dart index 0e6027b9075..e9c90c90ec1 100644 --- a/packages/smooth_app/lib/pages/prices/price_proof_card.dart +++ b/packages/smooth_app/lib/pages/prices/price_proof_card.dart @@ -7,6 +7,7 @@ import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; import 'package:smooth_app/generic_lib/buttons/smooth_large_button_with_icon.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/helpers/camera_helper.dart'; import 'package:smooth_app/pages/crop_parameters.dart'; @@ -27,10 +28,15 @@ class PriceProofCard extends StatelessWidget { Widget build(BuildContext context) { final PriceModel model = context.watch(); final AppLocalizations appLocalizations = AppLocalizations.of(context); - return SmoothCard( + return SmoothCardWithRoundedHeader( + title: appLocalizations.prices_proof_subtitle, + leading: const Icon(Icons.document_scanner_rounded), + contentPadding: const EdgeInsetsDirectional.symmetric( + horizontal: SMALL_SPACE, + vertical: MEDIUM_SPACE, + ), child: Column( children: [ - Text(appLocalizations.prices_proof_subtitle), if (model.proof != null) Image( image: NetworkImage( @@ -53,26 +59,31 @@ class PriceProofCard extends StatelessWidget { height: constraints.maxWidth, ), ), - SmoothLargeButtonWithIcon( - text: !model.hasImage - ? appLocalizations.prices_proof_find - : model.proofType == ProofType.receipt - ? appLocalizations.prices_proof_receipt - : appLocalizations.prices_proof_price_tag, - icon: !model.hasImage ? _iconTodo : _iconDone, - onPressed: model.proof != null - ? null - : () async { - final _ProofSource? proofSource = - await _ProofSource.select(context); - if (proofSource == null) { - return; - } - if (!context.mounted) { - return; - } - return proofSource.process(context, model); - }, + Padding( + padding: const EdgeInsetsDirectional.symmetric( + horizontal: SMALL_SPACE, + ), + child: SmoothLargeButtonWithIcon( + text: !model.hasImage + ? appLocalizations.prices_proof_find + : model.proofType == ProofType.receipt + ? appLocalizations.prices_proof_receipt + : appLocalizations.prices_proof_price_tag, + icon: !model.hasImage ? _iconTodo : _iconDone, + onPressed: model.proof != null + ? null + : () async { + final _ProofSource? proofSource = + await _ProofSource.select(context); + if (proofSource == null) { + return; + } + if (!context.mounted) { + return; + } + return proofSource.process(context, model); + }, + ), ), LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) => Row( diff --git a/packages/smooth_app/lib/pages/prices/product_price_add_page.dart b/packages/smooth_app/lib/pages/prices/product_price_add_page.dart index b9efbf90fbe..9f0cf80a2ee 100644 --- a/packages/smooth_app/lib/pages/prices/product_price_add_page.dart +++ b/packages/smooth_app/lib/pages/prices/product_price_add_page.dart @@ -21,7 +21,11 @@ import 'package:smooth_app/pages/prices/price_model.dart'; import 'package:smooth_app/pages/prices/price_proof_card.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; import 'package:smooth_app/pages/product/may_exit_page_helper.dart'; +import 'package:smooth_app/themes/smooth_theme.dart'; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; +import 'package:smooth_app/themes/theme_provider.dart'; import 'package:smooth_app/widgets/smooth_app_bar.dart'; +import 'package:smooth_app/widgets/smooth_expandable_floating_action_button.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; import 'package:smooth_app/widgets/will_pop_scope.dart'; @@ -80,6 +84,7 @@ class ProductPriceAddPage extends StatefulWidget { class _ProductPriceAddPageState extends State with TraceableClientMixin { final GlobalKey _formKey = GlobalKey(); + final ScrollController _scrollController = ScrollController(); @override Widget build(BuildContext context) { @@ -117,7 +122,11 @@ class _ProductPriceAddPageState extends State ), ], ), + backgroundColor: context.lightTheme() + ? context.extension().primaryLight + : null, body: SingleChildScrollView( + controller: _scrollController, padding: const EdgeInsets.all(LARGE_SPACE), child: Column( children: [ @@ -134,13 +143,15 @@ class _ProductPriceAddPageState extends State key: Key(model.elementAt(i).product.barcode), index: i, ), + const SizedBox(height: LARGE_SPACE), const PriceAddProductCard(), // so that the last items don't get hidden by the FAB const SizedBox(height: MINIMUM_TOUCH_SIZE * 2), ], ), ), - floatingActionButton: FloatingActionButton.extended( + floatingActionButton: SmoothExpandableFloatingActionButton( + scrollController: _scrollController, onPressed: () async => _exitPage( await _mayExitPage( saving: true, @@ -152,6 +163,10 @@ class _ProductPriceAddPageState extends State appLocalizations.prices_send_n_prices( model.length, ), + style: const TextStyle( + fontWeight: FontWeight.w600, + fontSize: 15.0, + ), ), ), ),