import 'dart:convert'; import 'package:flutter/material.dart'; import '../../../events/eventbus.dart'; import '../../../events/events.dart'; import '../../../generated/l10n.dart'; import '../../../models/product.dart'; import '../../../models/product_option.dart'; import '../../../utils/utils.dart'; import 'options_base.dart'; import 'rules.dart'; class QtyOptions extends OptionsBase { QtyOptions({@required Product product, @required int index, @required Map selections}) : super(product: product, index: index, selections: selections); @override State createState() { return new QtyOptionsState(); } } class QtyOptionsState extends OptionsBaseState { Map optionsState = new Map(); int thisLimitQty = 0; @override Widget build(BuildContext context) { return new ListView.builder( itemCount: 2, itemBuilder: (context, index) { if (index == 0) { return new Container( padding: new EdgeInsets.all(10.0), child: new Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ new Text( S.of(context).check_option_select_token(product.productAttributes[this.index].name), style: new TextStyle( fontSize: 12.5, ), overflow: TextOverflow.ellipsis, ), new Text( product.productAttributes[this.index].required ? S.of(context).check_option_is_required : S.of(context).check_option_is_optional, style: new TextStyle( fontSize: 10.0, color: new Color(0xFF999999) ), overflow: TextOverflow.ellipsis, ) ], ), ); } return _getOptionWidget(); } ); } @override void initState() { super.initState(); setState(() { product = widget.product; selections = widget.selections; index = widget.index; }); eventBus.on().listen((event) { setState(() { index = event.index; }); }); } void _onOptionTappedCallback(name, quantity, adjustAmount, int optIndex, ProductOption productOption) { Map opt = { 'name': name, 'quantity': quantity, 'adjust_amount': adjustAmount }; var cloneSelections = json.decode(json.encode(selections)); int idx = Utils.selectionsContains(cloneSelections, product.productAttributes[index].name, name); if (idx != -1) { if (quantity == 1) { cloneSelections[product.productAttributes[index].name.toUpperCase()][idx]['quantity'] += 1; optionsState[product.productAttributes[index].name][optIndex]['quantity'] = cloneSelections[product.productAttributes[index].name.toUpperCase()][idx]['quantity']; } else { if (cloneSelections[product.productAttributes[index].name.toUpperCase()][idx]['quantity'] - 1 > 0) { cloneSelections[product.productAttributes[index].name.toUpperCase()][idx]['quantity'] -= 1; optionsState[product.productAttributes[index].name][optIndex]['quantity'] = cloneSelections[product.productAttributes[index].name.toUpperCase()][idx]['quantity']; } else { (cloneSelections[product.productAttributes[index].name.toUpperCase()] as List).removeAt(idx); optionsState[product.productAttributes[index].name][optIndex]['quantity'] = 0; } } } else if (cloneSelections.containsKey(product.productAttributes[index].name.toUpperCase())) { (cloneSelections[product.productAttributes[index].name.toUpperCase()] as List).add(opt); optionsState[product.productAttributes[index].name][optIndex]['quantity'] = 1; } else { cloneSelections[product.productAttributes[index].name.toUpperCase()] = [opt]; optionsState[product.productAttributes[index].name][optIndex]['quantity'] = 1; } if (idx != -1 && (cloneSelections[product.productAttributes[index].name.toUpperCase()] as List).length == 0) { cloneSelections.remove(product.productAttributes[index].name.toUpperCase()); } setOptionsStateDisabled(product.productAttributes[index].name, false); setState(() { selections = cloneSelections; }); eventBus.fire(new OnAttributeSelectionsChanged(selections)); } Widget _getOptionWidget() { var row = Wrap( children: [], ); List productOptions = product.productAttributes[index].productOptions; if (!optionsState.containsKey(product.productAttributes[index].name)) { List> optionState = []; for (var i = 0; i < productOptions.length; i++) { int qty = 0; int idx = Utils.selectionsContains(selections, product.productAttributes[index].name, productOptions[i].name); if (idx != -1) { qty = selections[product.productAttributes[index].name.toUpperCase()][idx]['quantity']; } optionState.add({'name': product.productAttributes[index].productOptions[i].name, 'disabled': false, 'quantity': qty, 'check': false}); } optionsState[product.productAttributes[index].name] = optionState; } if (selections.containsKey(product.productAttributes[index].name.toUpperCase())) { Map attrExtraJson = Utils.stringToJson( product.productAttributes[index].extra); if (attrExtraJson != null) { var selectLimitIfFieldEqualsTo = Rule.getRule( attrExtraJson, Rule.RULE_SELECT_LIMIT_IF_FIELD_EQUALS_TO); if (selectLimitIfFieldEqualsTo != null) { if (selectLimitIfFieldEqualsTo is List) { for (var b = 0; b < (selectLimitIfFieldEqualsTo as List).length; b++) { Map selectLimitIfFieldEqualsTo1 = selectLimitIfFieldEqualsTo[b]; if (selectLimitIfFieldEqualsTo1.containsKey( Rule.RULE_KEY_FORCE_LIMITED)) { int limitQty = selectLimitIfFieldEqualsTo1[Rule .RULE_KEY_FORCE_LIMITED]; thisLimitQty = limitQty; if ((selections[product.productAttributes[index].name .toUpperCase()] as List).length >= limitQty) { disableOptionIfNotSelected(); } } else if (Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY]).length > 0) { if (selectLimitIfFieldEqualsTo1.containsKey(Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY])[0])) { int limitQty = selectLimitIfFieldEqualsTo1[Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY])[0]]; thisLimitQty = limitQty; if ((selections[product.productAttributes[index].name .toUpperCase()] as List).length >= limitQty) { disableOptionIfNotSelected(); } } } } } else { if (selectLimitIfFieldEqualsTo.containsKey( Rule.RULE_KEY_FORCE_LIMITED)) { int limitQty = selectLimitIfFieldEqualsTo[Rule .RULE_KEY_FORCE_LIMITED]; thisLimitQty = limitQty; if ((selections[product.productAttributes[index].name .toUpperCase()] as List).length >= limitQty) { disableOptionIfNotSelected(); } } else if (Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY]).length > 0) { if (selectLimitIfFieldEqualsTo.containsKey(Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY])[0])) { int limitQty = selectLimitIfFieldEqualsTo[Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY])[0]]; thisLimitQty = limitQty; if ((selections[product.productAttributes[index].name .toUpperCase()] as List).length >= limitQty) { disableOptionIfNotSelected(); } } } } } } for (var i = 0; i < productOptions.length; i++) { Map extraJson = Utils.stringToJson( productOptions[i].extra); if (extraJson != null) { Map exclusiveRule = Rule.getRule( extraJson, Rule.RULE_EXCLUSIVE_SELECTION); Map multiItemRule = Rule.getRule(extraJson, Rule.RULE_ACTUAL_QTY_IS); if (exclusiveRule != null) { if (thisLimitQty > 0 && !_checkOptionIsCheck(productOptions[i].name)) { optionsState[product.productAttributes[index].name][i]['disabled'] = true; } else { if (_checkOptionIsCheck(productOptions[i].name)) { setOptionsStateDisabled( product.productAttributes[index].name, true); optionsState[product.productAttributes[index] .name][i]['disabled'] = false; break; } } } if (multiItemRule != null) { if (_checkOptionIsCheck(productOptions[i].name)) { if (multiItemRule[Rule.RULE_ACTUAL_QTY_IS] > thisLimitQty - (selections[product.productAttributes[index].name.toUpperCase()] as List).length) { disableOptionIfNotSelected(); } } else { if (multiItemRule[Rule.RULE_ACTUAL_QTY_IS] > thisLimitQty - (selections[product.productAttributes[index].name.toUpperCase()] as List).length) { optionsState[product.productAttributes[index] .name][i]['disabled'] = true; } } } } } } List> optionState = optionsState[product.productAttributes[index].name]; for (var i = 0; i < optionState.length; i++) { Widget optionWidget = _getOptionQty( product.productAttributes[index].productOptions[i], optionState[i]['disabled'], optionState[i]['quantity'], i); row.children.add(optionWidget); } return row; } void disableOptionIfNotSelected() { setOptionsStateDisabled(product.productAttributes[index].name, true); for (var i = 0; i < optionsState[product.productAttributes[index].name].length; i++) { if (Utils.selectionsContains(selections, product.productAttributes[index].name, optionsState[product.productAttributes[index].name][i]['name']) != -1) { optionsState[product.productAttributes[index].name][i]['disabled'] = false; } } } bool _checkOptionIsCheck(String name) { if (Utils.selectionsContains(selections, product.productAttributes[index].name, name) != -1) { return true; } return false; } Widget _getOptionQty(ProductOption productOption, bool optDisabled, int quantity, int optIndex) { bool disabled = optDisabled; bool check = _checkOptionIsCheck(productOption.name); Map extraJson = Utils.stringToJson(productOption.extra); // Utils.jsonPrettyPrint(extraJson); double extraAdjustAmount = 0.0; if (extraJson != null) { var sizeBaseAdjustment = Rule.getRule(extraJson, Rule.RULE_ADJUSTMENT_BASED_ON_SELECTED_FIELD_VALUE); if (sizeBaseAdjustment != null) { if (sizeBaseAdjustment is List) { for (var i = 0; i < (sizeBaseAdjustment as List).length; i++) { Map sizeBaseAdjustment1 = sizeBaseAdjustment[i]; List attValues = Utils.getSelectedAttributeValue(selections, sizeBaseAdjustment1[Rule.RULE_KEY_FIELD_KEY]); if (attValues.length > 0 && sizeBaseAdjustment1.containsKey(attValues[0])) { extraAdjustAmount += sizeBaseAdjustment1[attValues[0]]; } } } else { List attValues = Utils.getSelectedAttributeValue(selections, sizeBaseAdjustment[Rule.RULE_KEY_FIELD_KEY]); if (attValues.length > 0 && sizeBaseAdjustment.containsKey(attValues[0])) { extraAdjustAmount += sizeBaseAdjustment[attValues[0]]; } } } var disabledRule = Rule.getRule(extraJson, Rule.RULE_DISABLED_IF_FIELD_EQUALS_TO); if (disabledRule != null) { if (disabledRule is List) { for (var i = 0; i < (disabledRule as List).length; i++) { Map disabledRule1 = disabledRule[i]; List attValues = Utils.getSelectedAttributeValue(selections, disabledRule1[Rule.RULE_KEY_FIELD_KEY]); if (attValues.length > 0 && disabledRule1.containsKey(attValues[0])) { disabled = true; } } } else { List attValues = Utils.getSelectedAttributeValue(selections, disabledRule[Rule.RULE_KEY_FIELD_KEY]); if (attValues.length > 0 && disabledRule.containsKey(attValues[0])) { disabled = true; } } } } return new Container( width: 100.0, height: 100.0, decoration: BoxDecoration( color: disabled ? disabledBackgroundColor : (check ? selectedBackgroundColor : deselectBackgroundColor), shape: BoxShape.rectangle, border: new Border.all( color: check ? selectedBorderColor : deselectBorderColor, width: 1.0, ), // borderRadius: BorderRadius.all(Radius.circular(10.0)), borderRadius: BorderRadius.only( topLeft: Radius.circular(10.0), topRight: Radius.circular(10.0), ), ), margin: new EdgeInsets.all(10.0).copyWith(right: 0.0), child: new Column( children: [ new GestureDetector( child: new Container( width: 100.0, height: 70.0, padding: new EdgeInsets.all(4.0), child: new Column( mainAxisAlignment: MainAxisAlignment.center, children: [ new Text( productOption.name, style: new TextStyle( fontSize: 14.0, color: check ? selectedTextColor : deselectTextColor, ), maxLines: 2, softWrap: true, overflow: TextOverflow.ellipsis, ), new Text( (productOption.adjustAmount + extraAdjustAmount) > 0 ? '+${(productOption.adjustAmount + extraAdjustAmount).toStringAsFixed(2)}' : '', style: new TextStyle( fontSize: 11.0, color: check ? selectedTextColor : new Color(0xFFABABAB), ), overflow: TextOverflow.ellipsis, ) ], ), ), onTap: () => disabled ? null : _onOptionTappedCallback( productOption.name, 1, productOption.adjustAmount + extraAdjustAmount, optIndex, productOption), ), new Container( width: 100.0, height: 28.0, decoration: BoxDecoration( color: disabled ? disabledBackgroundColor : (check ? selectedBackgroundColor : deselectBackgroundColor), shape: BoxShape.rectangle, border: new Border( top: new BorderSide( color: check ? selectedBorderColor : deselectBorderColor, width: 1.0, ), ), ), child: new Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ new Expanded( child: new GestureDetector( child: new Container( color: new Color(0x00000000), width: 49.0, height: 28.0, child: new Center( child: new Text( '${quantity}', style: new TextStyle( color: check ? selectedTextColor : new Color(0xFFABABAB), ), ), ), ), onTap: () => disabled ? null : _onOptionTappedCallback( productOption.name, 1, productOption.adjustAmount + extraAdjustAmount, optIndex, productOption), ), ), new Expanded( child: new GestureDetector( child: new Container( color: disabledBackgroundColor, width: 49.0, height: 28.0, child: new Center( child: new Text('-') ), ), onTap: () => (disabled || quantity == 0) ? null : _onOptionTappedCallback( productOption.name, -1, productOption.adjustAmount + extraAdjustAmount, optIndex, productOption), ), ), ], ), ) ], ), ); } void setOptionsStateDisabled(String attrName, bool disabled) { if (optionsState.containsKey(attrName)) { List> optionState = optionsState[attrName]; for (var i = 0; i < optionState.length; i++) { optionState[i]['disabled'] = disabled; } } } }