-
-
Notifications
You must be signed in to change notification settings - Fork 306
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: 5817 Product page: tab Data #5953
base: develop
Are you sure you want to change the base?
Changes from all commits
fbe346f
5af0043
cf7f12b
ec188f3
d334c45
742c7aa
eb59cc4
3725e04
a37da9b
7bc7e66
8822c9e
48d251c
d91f0b9
0cc45fb
3219365
735c82f
36a8f08
fab901a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||
import 'package:smooth_app/pages/product/product_page/raw_data/models/product_raw_data_category.dart'; | ||
import 'package:smooth_app/resources/app_icons.dart' as icons; | ||
|
||
extension CategoryLabelExt on ProductRawDataCategories { | ||
String toL10nString(AppLocalizations appLocalizations) => switch (this) { | ||
ProductRawDataCategories.labels => appLocalizations.label_refresh, | ||
ProductRawDataCategories.category => appLocalizations.category, | ||
ProductRawDataCategories.ingredients => appLocalizations.ingredients, | ||
ProductRawDataCategories.countries => | ||
appLocalizations.country_chooser_label_from_settings, | ||
ProductRawDataCategories.nutriment => appLocalizations.nutrition, | ||
ProductRawDataCategories.packaging => | ||
appLocalizations.packaging_information, | ||
ProductRawDataCategories.stores => | ||
appLocalizations.edit_product_form_item_stores_title, | ||
}; | ||
|
||
Widget toIcon() => switch (this) { | ||
ProductRawDataCategories.labels => const icons.Labels(), | ||
ProductRawDataCategories.category => const icons.Categories(), | ||
ProductRawDataCategories.ingredients => const icons.Ingredients(), | ||
ProductRawDataCategories.countries => const icons.Countries(), | ||
ProductRawDataCategories.nutriment => const icons.NutritionFacts(), | ||
ProductRawDataCategories.packaging => const icons.Packaging(), | ||
ProductRawDataCategories.stores => const icons.Stores(), | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import 'package:smooth_app/pages/product/product_page/raw_data/models/raw_data_element.dart'; | ||
|
||
class ProductRawDataCategory { | ||
const ProductRawDataCategory(this.category, this.rawDatas); | ||
|
||
final ProductRawDataCategories category; | ||
final List<ProductRawDataSubCategory> rawDatas; | ||
} | ||
|
||
enum ProductRawDataCategories { | ||
labels, | ||
category, | ||
ingredients, | ||
nutriment, | ||
packaging, | ||
stores, | ||
countries | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
sealed class ProductRawDataSubCategory {} | ||
|
||
class ProductRawDataElement extends ProductRawDataSubCategory { | ||
ProductRawDataElement(this.name); | ||
|
||
final String name; | ||
} | ||
|
||
class ProductRawDataElementDoubleText extends ProductRawDataSubCategory { | ||
ProductRawDataElementDoubleText(this.text1, this.text2); | ||
|
||
final String text1; | ||
final String text2; | ||
} | ||
|
||
class ProductRawDataSeeMoreButton extends ProductRawDataSubCategory {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:smooth_app/generic_lib/design_constants.dart'; | ||
import 'package:smooth_app/pages/product/product_page/raw_data/models/raw_data_element.dart'; | ||
import 'package:smooth_app/pages/product/product_page/raw_data/product_raw_data_element_item.dart'; | ||
import 'package:smooth_app/themes/theme_provider.dart'; | ||
|
||
class CategoryElementsListView extends StatefulWidget { | ||
const CategoryElementsListView({ | ||
required this.elements, | ||
this.controller, | ||
}); | ||
|
||
final List<ProductRawDataSubCategory> elements; | ||
final ScrollController? controller; | ||
|
||
@override | ||
State<StatefulWidget> createState() => _CategoryElementsListViewState(); | ||
} | ||
|
||
class _CategoryElementsListViewState extends State<CategoryElementsListView> { | ||
bool extended = false; | ||
|
||
void extendList() { | ||
setState(() { | ||
extended = true; | ||
}); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final List<ProductRawDataSubCategory> listToShow; | ||
if (extended) { | ||
listToShow = widget.elements; | ||
} else { | ||
listToShow = _shortenIfTooLong(widget.elements); | ||
} | ||
final Color dividerColor = | ||
context.lightTheme() ? const Color(0xFFF9F9F9) : Colors.white; | ||
|
||
return Padding( | ||
padding: const EdgeInsetsDirectional.only(start: 90.0), | ||
child: ListView.separated( | ||
controller: widget.controller, | ||
physics: const ClampingScrollPhysics(), | ||
shrinkWrap: true, | ||
padding: const EdgeInsetsDirectional.symmetric( | ||
vertical: MEDIUM_SPACE, | ||
), | ||
itemBuilder: (BuildContext context, int index) { | ||
return Container( | ||
margin: const EdgeInsetsDirectional.only(start: 21), | ||
child: ProductRawDataElementItem( | ||
listToShow[index], | ||
() => extendList(), | ||
), | ||
); | ||
}, | ||
separatorBuilder: (BuildContext context, _) => Divider( | ||
color: dividerColor, | ||
), | ||
itemCount: listToShow.length, | ||
), | ||
); | ||
} | ||
|
||
static const int _SUB_LIST_LENGTH = 3; | ||
|
||
List<ProductRawDataSubCategory> _shortenIfTooLong( | ||
List<ProductRawDataSubCategory> list) { | ||
if (list.length > _SUB_LIST_LENGTH) { | ||
final List<ProductRawDataSubCategory> toReturn = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A more generic way is to use the following syntax:
|
||
<ProductRawDataSubCategory>[ | ||
...list.sublist(0, _SUB_LIST_LENGTH), | ||
ProductRawDataSeeMoreButton() | ||
]; | ||
return toReturn; | ||
} else { | ||
return list; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
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/pages/product/product_page/raw_data/category_label_ext.dart'; | ||
import 'package:smooth_app/pages/product/product_page/raw_data/models/product_raw_data_category.dart'; | ||
import 'package:smooth_app/pages/product/product_page/raw_data/product_raw_data_category_elements_item.dart'; | ||
import 'package:smooth_app/resources/app_icons.dart' as icons; | ||
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'; | ||
|
||
class ProductRawDataCategoryItem extends StatelessWidget { | ||
const ProductRawDataCategoryItem(this.category, {this.controller}); | ||
|
||
final ProductRawDataCategory category; | ||
final ScrollController? controller; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final AppLocalizations appLocalizations = AppLocalizations.of(context); | ||
|
||
return Column( | ||
crossAxisAlignment: CrossAxisAlignment.start, | ||
children: <Widget>[ | ||
_ProductRawDataCategoryTile( | ||
category.category.toIcon(), | ||
category.category.toL10nString(appLocalizations), | ||
), | ||
CategoryElementsListView( | ||
elements: category.rawDatas, | ||
controller: controller, | ||
), | ||
]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing trailing comma |
||
} | ||
} | ||
|
||
class _ProductRawDataCategoryTile extends StatelessWidget { | ||
const _ProductRawDataCategoryTile(this.icon, this.label); | ||
|
||
final Widget icon; | ||
final String label; | ||
@override | ||
Widget build(BuildContext context) { | ||
final bool lightTheme = context.lightTheme(); | ||
final Color contentColor = lightTheme | ||
? context.extension<SmoothColorsThemeExtension>().primaryBlack | ||
: Colors.white; | ||
|
||
final Color dividerColor = | ||
lightTheme ? const Color(0xFFF9F9F9) : Colors.white; | ||
|
||
return Container( | ||
color: const Color(0xFFFEFEFE), | ||
child: Column( | ||
children: <Widget>[ | ||
Container( | ||
margin: | ||
const EdgeInsetsDirectional.symmetric(vertical: MEDIUM_SPACE), | ||
//This rows of rows is here to have this Layout Spaced through the lign | ||
child: Row( | ||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||
children: <Widget>[ | ||
//Element icon + label | ||
Row( | ||
children: <Widget>[ | ||
const SizedBox(width: 31.0), | ||
IconTheme( | ||
data: IconThemeData( | ||
color: contentColor, | ||
size: 18.0, | ||
), | ||
child: icon, | ||
), | ||
const SizedBox(width: MEDIUM_SPACE), | ||
Text(label), | ||
], | ||
), | ||
//Edit button | ||
const Row( | ||
children: <Widget>[ | ||
IconTheme( | ||
data: IconThemeData( | ||
color: Colors.grey, | ||
size: 18.0, | ||
), | ||
child: icons.Edit(), | ||
), | ||
SizedBox(width: 28.0), | ||
], | ||
), | ||
], | ||
), | ||
), | ||
Divider( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you need a Divider of 0? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the divider default value is not 0 but 16 |
||
color: dividerColor, | ||
height: 0, | ||
) | ||
], | ||
), | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||
import 'package:smooth_app/pages/product/product_page/raw_data/models/raw_data_element.dart'; | ||
|
||
class ProductRawDataElementItem extends StatelessWidget { | ||
const ProductRawDataElementItem( | ||
this.element, | ||
this.onSeeMoreTap, { | ||
this.controller, | ||
}); | ||
|
||
final ProductRawDataSubCategory element; | ||
final ScrollController? controller; | ||
final Function() onSeeMoreTap; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
switch (element.runtimeType) { | ||
case const (ProductRawDataElement): | ||
return Text((element as ProductRawDataElement).name); | ||
case const (ProductRawDataElementDoubleText): | ||
return Row( | ||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||
children: <Widget>[ | ||
Text((element as ProductRawDataElementDoubleText).text1), | ||
Row( | ||
children: <Widget>[ | ||
Text((element as ProductRawDataElementDoubleText).text2), | ||
const SizedBox( | ||
width: 29.0, | ||
) | ||
], | ||
) | ||
], | ||
); | ||
case const (ProductRawDataSeeMoreButton): | ||
{ | ||
final AppLocalizations appLocalizations = | ||
AppLocalizations.of(context); | ||
return InkWell( | ||
onTap: () => onSeeMoreTap(), | ||
child: Text(appLocalizations.tap_for_more), | ||
); | ||
} | ||
default: | ||
throw FormatException('Invalid class ${element.runtimeType}'); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ShrinkWrap is your enemy. Why do you use it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is wrong with ShrinkWrap ?
In my case, it is needed to not have a crash due to ListView inside the other list view.