Skip to content

Instantly share code, notes, and snippets.

@followthemoney1
Last active April 6, 2020 11:24
Show Gist options
  • Save followthemoney1/a1852b94aa1b64fd6e766d5685992b7d to your computer and use it in GitHub Desktop.
Save followthemoney1/a1852b94aa1b64fd6e766d5685992b7d to your computer and use it in GitHub Desktop.
/**
 * Created by Dmitry Diachenko on Feb 18, 2020
 * powered by leaditteam.com
 **/

//MARK: widget ext
extension WidgetExtension on Widget {
  Widget setVisibility(VisibilityFlag flag) {
    return MyVisibility(visibility: flag, child: this);
  }

  Widget expand() {
    return Expanded(child: this);
  }

  Widget paddingAll(double value) {
    return Padding(
      padding: EdgeInsets.all(value),
      child: this,
    );
  }

  Widget paddingOnly(
      {double left = 0, double right = 0, double top = 0, double bottom = 0}) {
    return Padding(
      padding: EdgeInsets.only(
        left: left != 0 ? left : 0,
        right: right != 0 ? right : 0,
        top: top != 0 ? top : 0,
        bottom: bottom != 0 ? bottom : 0,
      ),
      child: this,
    );
  }

  Widget addOnTap(Function onTap) {
    return GestureDetector(
      onTap: onTap,
      child: this,
    );
  }

  Widget insideScroll() {
    return SingleChildScrollView(child: this);
  }

  Widget insideScrollAndExpand() {
    return Expanded(child: SingleChildScrollView(child: this));
  }

  Widget addOnTapAnimation(
      {@required Function onTap, int animation_miliseconds = 200}) {
    return AnimatedWidgetOnClick(
      child: this,
      onTap: onTap,
      animation_miliseconds: animation_miliseconds,
    );
  }
}

//MARK : future   /-native_progress_hud: ^1.0.3
extension MyFuture<T> on Future<T> {
  Future<T> withProgressBar({BuildContext context}) async {
    NativeProgressHud.showWaiting(); // show hud
    var res;
    try {
      res = await this;
    } catch (e) {
      print(e);
    }
    await Future.delayed(Duration(microseconds: 100), null); //for visibility
    NativeProgressHud.hideWaiting();

    return res;
  }
}

//MARK: static methods
Widget showSnackWithoutButton(
    {@required BuildContext context, @required String text}) {
  Scaffold.of(context).showSnackBar(SnackBar(
    content: Text(text),
    duration: Duration(seconds: 3),
  ));
}

//MARK: supportive classes
class AnimatedWidgetOnClick extends StatefulWidget {
  Widget child;
  Function onTap;
  int animation_miliseconds;

  AnimatedWidgetOnClick(
      {@required this.child, @required this.onTap, this.animation_miliseconds});

  @override
  _AnimatedWidgetOnClickState createState() => _AnimatedWidgetOnClickState();
}

class _AnimatedWidgetOnClickState extends State<AnimatedWidgetOnClick>
    with SingleTickerProviderStateMixin {
  double _scale;
  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: widget.animation_miliseconds),
      lowerBound: 0.0,
      upperBound: 0.1,
    )..addListener(() {
        setState(() {});
      });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _onTapDown(TapDownDetails details) {
    _controller.forward();
  }

  void _onTapUp(TapUpDetails details) {
    _controller.reverse();
  }

  void _onTap() {
    if (widget.onTap != null) _playAnimation();
  }

  Future<void> _playAnimation() async {
    try {
      await _controller.forward().orCancel;
      await _controller.reverse().orCancel;
      widget.onTap();
    } on TickerCanceled {
      print('Error animation');
    }
  }

  @override
  Widget build(BuildContext context) {
    _scale = 1 - _controller.value;

    return RawGestureDetector(
      gestures: {
        AllowMultipleGestureRecognizer: GestureRecognizerFactoryWithHandlers<
            AllowMultipleGestureRecognizer>(
          () => AllowMultipleGestureRecognizer(),
          (AllowMultipleGestureRecognizer instance) {
            instance
              ..onTap = () async {
                _onTap();
              };
          },
        )
      },
      child: Transform.scale(
        scale: _scale,
        child: widget.child,
      ),
    );
  }
}

class AllowMultipleGestureRecognizer extends TapGestureRecognizer {
  @override
  void rejectGesture(int pointer) {
    acceptGesture(pointer);
  }
}

extension HexColor on Color {
  /// String is in the format "aabbcc" with an optional leading "#".
  static Color fromHex(String hexString) {
    final buffer = StringBuffer();
    if (hexString.length == 6 || hexString.length == 7) buffer.write('ff');
    buffer.write(hexString.replaceFirst('#', ''));
    return Color(int.parse(buffer.toString(), radix: 16));
  }

  /// Prefixes a hash sign if [leadingHashSign] is set to `true` (default is `true`).
  String toHex({bool leadingHashSign = true}) => '${leadingHashSign ? '#' : ''}'
      '${alpha.toRadixString(16).padLeft(2, '0')}'
      '${red.toRadixString(16).padLeft(2, '0')}'
      '${green.toRadixString(16).padLeft(2, '0')}'
      '${blue.toRadixString(16).padLeft(2, '0')}';
}
class ProductDetailPresenter implements MainCallback, FindPlaceCallback {
  ProductDetailInterface _view;
  FirebaseManager _firebaseManager = new FirebaseManager();
  NetworkSharedPreferences _networkSharedPreferences =
      NetworkSharedPreferences();
  var placeId;
  var productId;
  var acceptComments = false;
  var acceptPhotoReview = false;

  ProductDetailPresenter(this._view, this.placeId, this.productId) {
    _init();
  }

  void _init() async {
    acceptComments = await _networkSharedPreferences.returnAcceptComments();
    acceptPhotoReview = await _networkSharedPreferences.returnPhotoReview();
    _view.setCommentsAndPhotosPermission(acceptComments, acceptPhotoReview);
  }

  void getProductById() async {
    var _firebaseOneMenuProduct =
        await _firebaseManager.getMenuProductByMenuId(productId);
    if (_firebaseOneMenuProduct == null) {
      _view.onError("Find product in database error");
      return;
    }

    _getPhotos(placeId, _firebaseOneMenuProduct.id);
    _getReviews(placeId, _firebaseOneMenuProduct.id);
    _initWishList();
    _view.onProductFind(_firebaseOneMenuProduct);
  }

  void _initWishList() {
    _firebaseManager.getMealList(placeId, (List<String> wishList) {
      _firebaseManager.getProductsFromWishList(wishList, this);
    });
  }

  void _getPhotos(var placeId, var productId) async {
    _firebaseManager.getProductPhotos(placeId, productId, this);
  }

  void _getReviews(var placeId, var productId) {
    _firebaseManager.getProductReviews(placeId, productId, this);
  }

  void addReview(String productId, String placeId, String text,
      double _reviewRating) async {
    FirebaseReviewUser review = FirebaseReviewUser();
    review.rating = _reviewRating;
    review.createdAt = Timestamp.now().toDate();
    review.authorId = await _firebaseManager.getCurrentUserId();
    review.authorName = await _firebaseManager.getCurrentUserName();
    review.text = text;

    if (review.authorName == null) review.authorName = "Unknown";

    _firebaseManager.addReview(productId, placeId, review);
  }

  void addPhoto(File image, String productId, String placeId) {
    _firebaseManager.uploadProductPhoto(image, productId, placeId);
  }

  @override
  void onError(err) {
    _view.onError(err);
  }

  @override
  void onSuccess<T>(List<T> successObj) {
    if (T == FirebaseReviewImage) {
      _view.updateProductImages(successObj as List<FirebaseReviewImage>);
    } else if (T == FirebaseReviewUser) {
      _view.updateProductReviews(successObj as List<FirebaseReviewUser>);
    }
  }

  @override
  onFind(List<FirebaseOneMenuProduct> products) {
    var contain = false;
    products.forEach((p) {
      if (p.id == productId) contain = true;
    });
    return _view.productInWishList(contain);
  }

  @override
  onFirebasePlaceFind(FirebasePlaceObject firebasePlace) {
    // MARK: implement onFirebasePlaceFind
    return null;
  }

  @override
  onNothingFind(String response) {
    // MARK: implement onNothingFind
    return _view.onError(response);
  }
}
class ProductDetail extends StatefulWidget {
  static String tag = 'product_detail';
  var productId;
  var placeId;

  ProductDetail(this.productId, this.placeId);

  @override
  _ProductDetailState createState() => _ProductDetailState(productId, placeId);
}

class _ProductDetailState extends State<ProductDetail>
    implements ProductDetailInterface {
  var productId;
  var placeId;

  _ProductDetailState(this.productId, this.placeId);

  var homeScaffoldKey = new GlobalKey<ScaffoldState>();
  final _reviewController = TextEditingController();

  ProductDetailPresenter presenter;
  var _enableReviewButton = false;
  var _acceptComments = false;
  var _acceptPhotoReview = false;
  double _reviewRating = 0.0;

  FirebaseOneMenuProduct product;
  List<FirebaseReviewImage> _firebaseImages;
  List<FirebaseReviewUser> _firebaseReviews;
  FirebaseManager _firebaseManager = new FirebaseManager();
  bool inWishList = false;

  @override
  void initState() {
    super.initState();
    presenter = ProductDetailPresenter(this,placeId,productId);
    presenter.getProductById();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: homeScaffoldKey,
      appBar: PreferredSize(
          preferredSize: Size.fromHeight(CustomAppBar.APP_BAR_SIZE),
          // here the desired height
          child: _appBar()),
      body: Center(
        child: Column(children: <Widget>[
          Expanded(
              child: MyVisibility(
            visibility: (product != null
                ? VisibilityFlag.visible
                : VisibilityFlag.invisible),
            child: ListView(
              children: <Widget>[
                _productImage(),
                _ingridients(),
                _photos(),
                _nutrition(),
                _reviews(),
                _addReview(),
              ],
            ),
          )),
          _bottomView()
        ]),
      ),
    );
  }

  Widget _appBar() => CustomAppBar(
        backIconPress: () {
          Navigator.pop(context);
        },
        settingsIconVisibility: false,
      );

  Widget _productImage() => new Container(
      height: 180.0,
      child: Stack(
        alignment: AlignmentDirectional.bottomStart,
        children: <Widget>[
          Stack(children: <Widget>[
            (product == null ||
                    product.downloadUrl == null ||
                    product.downloadUrl.isEmpty)
                ? Image.asset(
                    Images.PRODUCT_PLACEHOLDER,
                    fit: BoxFit.fitWidth,
                    width: double.infinity,
                  )
                : Image.network(
                    product.downloadUrl,
                    fit: BoxFit.fitWidth,
                    width: double.infinity,
                  ),
            Positioned(
              child: _addIcon(),
              right: 1.0,
              top: 3.0,
            ),
          ]),
          Padding(
            padding: EdgeInsets.only(
                left: Constants.PADDING_SMALL_4,
                bottom: Constants.PADDING_MEDIUM_24),
            child: Text((product == null ? "" : product.item_name),
                maxLines: 1,
                style: TextStyle(
                    color: Colors.white,
                    fontSize: 18.0,
                    fontWeight: FontWeight.bold)),
          ),
          Padding(
              padding: EdgeInsets.only(
                  left: Constants.PADDING_SMALL_4,
                  bottom: Constants.PADDING_SMALL_4),
              child: Text(
                  (product != null &&
                          double.parse(product.calories.toString()) != null
                      ? "${double.parse(product.calories.toString()).round().toString()} calories"
                      : "n/a calories"),
                  maxLines: 1,
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 14.0,
                  ))),
        ],
      ));

  Widget _addIcon() {
    var addedToWishListIcon = Icons.delete_forever;
    return IconButton(
        icon: HighLightedIcon(
          (!inWishList ? Icons.add_circle : addedToWishListIcon),
          color: (!inWishList ? Colors.white : Colors.orange),
          size: 30.0,
        ),
        onPressed: () {
          _firebaseManager.changeDishList(placeId, product, null);
        });
  }

  Widget _ingridients() => MyVisibility(
      visibility:
          (product != null ? VisibilityFlag.visible : VisibilityFlag.gone),
      child: new ExpansionTile(
          backgroundColor: Colors.grey[100],
          title: new Text("Ingridients"),
          children: (product != null
              ? product.ingredients.split(", ").map((m) {
                  return Container(
                      width: double.infinity,
                      child: Padding(
                          padding: EdgeInsets.only(
                              left: Constants.PADDING_MEDIUM_16, bottom: 3.0),
                          child: Text(
                            m,
                          )));
                }).toList()
              : List<Widget>())));

  Widget _photos() => MyVisibility(
      visibility: (_firebaseImages != null
          ? VisibilityFlag.visible
          : VisibilityFlag.gone),
      child: new ExpansionTile(
          backgroundColor: Colors.grey[100],
          title: new Text(
              "Photos ${(_firebaseImages != null ? "(" + _firebaseImages.length.toString() + ")" : "")}"),
          children: <Widget>[
            GridView.count(
                shrinkWrap: true,
                physics: ClampingScrollPhysics(),
                crossAxisCount: 2,
                children: (_firebaseImages != null
                    ? _firebaseImages.map((m) {
                        return Container(
                            height: 40.0,
                            width: 20.0,
                            padding: EdgeInsets.only(left: 4.0, right: 4.0),
                            child: Image.network(m.imagePath));
                      }).toList()
                    : List<Widget>())),
          ]));

  Widget _nutrition() => MyVisibility(
      visibility:
          (product != null ? VisibilityFlag.visible : VisibilityFlag.gone),
      child: new ExpansionTile(
        backgroundColor: Colors.grey[100],
        title: new Text("Nutrition"),
        children: <Widget>[
          Container(
              height: CircleNutrition.CIRCLE_RADIUS + 10.0,
              child: ListView(
                  padding: EdgeInsets.only(bottom: 10.0),
                  scrollDirection: Axis.horizontal,
                  children: <Widget>[
                    _addIndicator("calories", product?.calories),
                    _addIndicator("sodium", product?.sodium),
                    _addIndicator("fat", product?.total_fat),
                    _addIndicator("protein", product?.protein),
                    _addIndicator("calcium", product?.calcium),
                    _addIndicator("iron", product?.iron),
                    _addIndicator("sugars", product?.sugars),
                    _addIndicator("vit. A", product?.vitamin_a),
                    _addIndicator("vit. C", product?.vitamin_c),
                    _addIndicator("cholesterol", product?.cholesterol),
                  ])),
        ],
      ));

  Widget _addIndicator(name, count) {
    if (count != null) {
      String c;
      try {
        c = (count as double).round().toString();
      } catch (e) {
        c = (count as int).round().toString();
      }
      return Padding(
          padding: EdgeInsets.only(left: 3.0, right: 1.0),
          child: CircleNutrition(c, name));
    } else
      return Container();
  }

  Widget _reviews() => MyVisibility(
      visibility: (_firebaseReviews != null
          ? VisibilityFlag.visible
          : VisibilityFlag.gone),
      child: new ExpansionTile(
          backgroundColor: Colors.grey[100],
          title: new Text(
              "Reviews ${(_firebaseReviews != null ? "(" + _firebaseReviews.length.toString() + ")" : "")}"),
          children: (_firebaseReviews != null
              ? _firebaseReviews.map((_review) {
                  return Review(_review);
                }).toList()
              : List<Widget>())));

  Widget _addReview() => Container(
      color: Colors.white70,
      child: Padding(
        padding: EdgeInsets.only(
            top: Constants.PADDING_SMALL_8,
            left: Constants.PADDING_MEDIUM_16,
            right: Constants.PADDING_MEDIUM_16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text("Leave Review",
                style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 20.0,
                    color: Colors.black)),
            Padding(
                padding: EdgeInsets.only(
                  top: Constants.PADDING_SMALL_8,
                ),
                child: Text("Your Rating:",
                    style: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 14.0,
                        color: Colors.grey[700]))),
            Padding(
                padding: EdgeInsets.only(
                    top: Constants.PADDING_MEDIUM_16,
                    bottom: Constants.PADDING_MEDIUM_16),
                child: Row(
                  children: <Widget>[
                    StarRating(
                      allowHalfRating: true,
                      size: 28.0,
                      rating: _reviewRating,
                      color: Colors.orange,
                      borderColor: Colors.orange,
                      starCount: 5,
                      onRatingChanged: (rating) => setState(
                            () {
                              this._reviewRating = rating;
                              if (_reviewController.text.isNotEmpty &&
                                  _reviewRating > 0.0)
                                _enableReviewButton = true;
                              else
                                _enableReviewButton = false;
                            },
                          ),
                    ),
                    Padding(
                        padding:
                            EdgeInsets.only(left: Constants.PADDING_MEDIUM_24),
                        child: Text(
                          _reviewRating.toStringAsFixed(2),
                          style: TextStyle(
                              fontWeight: FontWeight.bold, fontSize: 16.0),
                        )),
                  ],
                )),
            Container(
              width: double.infinity,
              height: 120.0,
              decoration:
                  new BoxDecoration(border: new Border.all(color: Colors.grey)),
              child: TextField(
                controller: _reviewController,
                maxLines: 30,
                onChanged: (text) {
                  if (text.isNotEmpty && _reviewRating > 0.0)
                    _enableReviewButton = true;
                  else
                    _enableReviewButton = false;
                },
                decoration: InputDecoration(
                    border: InputBorder.none,
                    hintText: 'Please write a review'),
              ),
            ),
            MaterialButton(
              onPressed: (_enableReviewButton
                  ? _addReviewClick
                  : null),
              color: (_enableReviewButton & _acceptComments
                  ? Colors.green
                  : Colors.grey),
              child: Text(
                "Leave Review",
                style: TextStyle(
                    color: Colors.white,
                    fontWeight: FontWeight.bold,
                    fontSize: 18.0),
              ),
            )
          ],
        ),
      ));

  Widget _bottomView() => Container(
      height: Constants.PADDING_BOTTOM_SHEET,
      width: double.infinity,
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.end,
        children: <Widget>[
          Expanded(
              child: Container(
            height: double.infinity,
            color: (_acceptPhotoReview ? Colors.green : Colors.grey),
            child: FlatButton.icon(
                icon: Icon(
                  Icons.photo_camera,
                  color: Colors.white,
                ),
                onPressed: _addPhoto,
                padding: EdgeInsets.all(0),
                label: Text("TAKE A PHOTO",
                    style: TextStyle(color: Colors.white, fontSize: 16.0))),
          )),
        ],
      ));

  void _addReviewClick() {
    if (!_acceptComments) {
      onError('The restaurant has forbidden to add comments');
      return;
    }
    //MARK: add this floy when we have a real user
    presenter.addReview(
        productId, placeId, _reviewController.text, _reviewRating);
    setState(() {
      _reviewController.text = "";
      _reviewRating = 0;
      _enableReviewButton = false;
    });
  }

  void _addPhoto() async {
    if(!_acceptPhotoReview) {
      onError('The restaurant has forbidden to add photos');
      return;
    }

    var image = await ImagePicker.pickImage(source: ImageSource.camera);

    ( (image != null) ?
    presenter.addPhoto(image, productId, placeId) :
    onError("Image is empty"));
  }

  @override
  void setCommentsAndPhotosPermission(
      bool acceptComments, bool acceptPhotoReview) {
    setState(() {
      _acceptComments = acceptComments;
      _acceptPhotoReview = acceptPhotoReview;
    });
  }

  @override
  void onError(var error) {
    if (error != null && homeScaffoldKey.currentState != null)
      homeScaffoldKey.currentState.showSnackBar(
        SnackBar(content: Text(error)),
      );
  }

  @override
  void onProductFind(_product) {
    setState(() {
      product = _product;
    });
  }

  @override
  void updateProductImages(List<FirebaseReviewImage> firebaseImages) {
    setState(() {
      _firebaseImages = firebaseImages;
    });
  }

  @override
  void updateProductReviews(List<FirebaseReviewUser> firebaseReviews) {
    setState(() {
      _firebaseReviews = firebaseReviews;
    });
  }

  @override
  void productInWishList(bool t) {
    setState(() {
      inWishList = t;
      debugPrint("productInWishList  $t");
    });
  }
}
class HomePage extends StatefulWidget {
  static String tag = 'home_page';

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> implements HomePageInterface {
  static final SELECT_PLACE = "Select place";
  static const platform = const MethodChannel('show_home_screen');

  HomePresenter presenter;
  var homeScaffoldKey = new GlobalKey<ScaffoldState>();
  var _listViewController = ScrollController();
  ProgressBar _progressBar = ProgressBar();

  var _textForPlaceSelector = SELECT_PLACE;
  var _visibilityFlag = VisibilityFlag.invisible;
  var _textForMainViewSelector = Constants.TEXT_ON_NOTHING_SELECTED;
  var _placePickerHeight = 60.0;

  List<FirebaseOneMenuProduct> _products;
  List<String> _wishList;
  FirebasePlaceObject _firebasePlaceObject;

  @override
  void initState() {
    super.initState();
    presenter = new HomePresenter(context, this);
    platform.setMethodCallHandler(_handleMethod);
    _listViewController.addListener(_onListViewScroll);
  }

  @override
  void dispose() {
    _listViewController.removeListener(_onListViewScroll);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: homeScaffoldKey,
      appBar: PreferredSize(
          preferredSize: Size.fromHeight(CustomAppBar.APP_BAR_SIZE),
          // here the desired height
          child: _appBar()),
      body: Center(
        child: Column(
          children: <Widget>[
             GestureDetector(
                    onTap: presenter.openPlacePicker, child: _placePicker()),
            Flexible(flex: 24, child: _productsListView()),
            _bottomView(),
          ],
        ),
      ),
    );
  }

  Widget _appBar() => CustomAppBar(
        backIconVisibility: false,
        settingsIconVisibility: false,
      );
  Widget _placePicker() => Container(
      height: _placePickerHeight,
      child:Padding(
      padding: EdgeInsets.only(
          top: Constants.PADDING_SMALL_4,
          bottom: Constants.PADDING_SMALL_4,
          left: Constants.PADDING_SMALL_12,
          right: Constants.PADDING_SMALL_12),
      child: Card(
        child: Container(
            width: double.infinity,
            child: Padding(
              padding: EdgeInsets.only(
                left: Constants.PADDING_MEDIUM_18,
              ),
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Expanded(
                      flex: 3,
                      child: Text(
                        _textForPlaceSelector,
                        maxLines: 1,
                      )),
                  Expanded(
                      flex: 1,
                      child: MyVisibility(
                        child: IconButton(
                          icon: Icon(Icons.clear),
                          onPressed: () =>
                              changeClearIconVisibility(false, null),
                        ),
                        visibility: _visibilityFlag,
                      ))
                ],
              ),
            )),
      )));


  Widget _productsListView() => Stack(
        alignment: AlignmentDirectional.center,
        children: <Widget>[
          MyVisibility(
              visibility: (_products != null
                  ? VisibilityFlag.visible
                  : VisibilityFlag.invisible),
              child: ListView.builder(
                controller: _listViewController,
                itemCount: (_products != null ? _products.length : 0),
                itemBuilder: (context, i) {
                  return MenuProduct(
                    _products.elementAt(i),
                    _firebasePlaceObject.docId,
                    context,
                    inWishList: (_wishList != null
                        ? _wishList.contains(_products.elementAt(i).id)
                        : false),
                  );
                },
              )),
          MyVisibility(
              visibility: (_products == null
                  ? VisibilityFlag.visible
                  : VisibilityFlag.invisible),
              child: Padding(
                  padding: EdgeInsets.all(31.0),
                  child: Text(
                    _textForMainViewSelector,
                    textAlign: TextAlign.center,
                    style: TextStyle(
                        fontSize: 19.0,
                        fontWeight: FontWeight.w300,
                        color: Colors.grey[600],
                        fontFamily: "Roboto"),
                  )))
        ],
      );

  Widget _bottomView() => Container(
      height: Constants.PADDING_BOTTOM_SHEET,
      width: double.infinity,
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.end,
        children: <Widget>[
          Expanded(
              child: Container(
            height: double.infinity,
            color: Colors.green,
            child: FlatButton.icon(
                icon: Icon(
                  Icons.restaurant_menu,
                  color: Colors.white,
                ),
                onPressed: _goToScanMenu,
                padding: EdgeInsets.all(0),
                label: Text("SCAN MENU",
                    style: TextStyle(color: Colors.white, fontSize: 16.0))),
          )),
          Expanded(
              child: Container(
            height: double.infinity,
            color: (_wishList != null && _wishList.length > 0
                ? Colors.orange
                : Colors.grey[700]),
            child: FlatButton.icon(
                icon: Icon(
                  Icons.shopping_basket,
                  color: Colors.white,
                ),
                onPressed: _onWishListPressed,
                label: Text(
                    "MEAL ${(_wishList != null && _wishList.length > 0 ? '(' + _wishList.length.toString() + ')' : "")} ",
                    style: TextStyle(color: Colors.white, fontSize: 16.0))),
          )),
        ],
      ));

   _onListViewScroll(){
     setState(() {
       //_placePickerHeight = _listViewController.offset * _placePickerDefaultHeight / (MenuProduct.LIST_VIEW_ITEM_HEIGHT * _products.length);
       print('_placePickerHeight: $_placePickerHeight');
     });
   }

  void _onWishListPressed() {
    if (_wishList != null && _wishList.length > 0)
      Navigator.push(
        context,
        MaterialPageRoute(
            builder: (context) =>
                MealPage(_firebasePlaceObject.docId, _products)),
      );
  }

  @override
  void changeClearIconVisibility(bool visible, FirebasePlaceObject place) {
    setState(() {
      if (visible) {
        _visibilityFlag = VisibilityFlag.visible;
        _textForPlaceSelector = place.place_name;
        _firebasePlaceObject = place;
      } else {
        _visibilityFlag = VisibilityFlag.invisible;
        _textForPlaceSelector = SELECT_PLACE;
        _products = null;
        _firebasePlaceObject = null;
        _firebasePlaceObject = null;
        _wishList = null;
        _textForMainViewSelector = Constants.TEXT_ON_NOTHING_SELECTED;
      }
    });
  }

  @override
  void updatePlaceResultsViews(List<FirebaseOneMenuProduct> products) {
    setState(() {
      _products = products;
    });
  }

  @override
  void onErrorPlacePicker(PlacesAutocompleteResponse response) {
    onError(response.errorMessage);
    setState(() {
      _products = null;
      _textForMainViewSelector = Constants.TEXT_ON_RESTAURAN_NOT_FOUND;
    });
  }

  @override
  void onError(String error) {
    if (error != null && homeScaffoldKey.currentState != null)
      homeScaffoldKey.currentState.showSnackBar(
        SnackBar(content: Text(error)),
      );
    setState(() {
      _textForMainViewSelector = Constants.TEXT_ON_RESTAURAN_NOT_FOUND;
    });
  }

  void _goToScanMenu() async {
    if (_products == null) {
      onError("Place not selected");
      return;
    }
    try {
      var data = json.encode(
          {'placeId': _firebasePlaceObject.docId, "products": _products});
      debugPrint(data);
      final int result = await platform.invokeMethod('showHomeScreen', data);
    } on PlatformException catch (e) {
      debugPrint(e.toString());
    }
  }

  Future<dynamic> _handleMethod(MethodCall call) async {
    switch (call.method) {
      case "showDetailScreen":
        debugPrint(call.arguments);
        Map<dynamic, dynamic> ar = json.decode(call.arguments);
        debugPrint(" scan: " +
            ar["productId"].toString() +
            " " +
            ar["placeId"].toString());
        await Navigator.push(
          context,
          MaterialPageRoute(
              builder: (context) => ProductDetail(
                  ar["productId"].toString(), ar["placeId"].toString())),
        );

        _goToScanMenu();
        return new Future.value("");
    }
  }

  @override
  void showProgressBar(bool visability) {
    (visability
        ? _progressBar.showProgressBar(context)
        : _progressBar.hideProgressBar());
  }

  @override
  void updateWishList(List<String> w) {
    setState(() {
      _wishList = w;
      debugPrint('wish list = ${w}');
    });
  }
}

class MyTextInput extends StatefulWidget {
  String labelText;
  TextEditingController controller;
  TextInputType textInputType;
  TextInputAction textInputAction;
  FocusNode focusNode;
  bool withoutBorder;

  bool obscureText;
  var inputFlex;
  var align;
  String hint;
  var nextFocus;

  var passwordType;
  final void Function() onChange;
  final void Function() onDone;
  String temp;
  bool jumpToStart;
  bool isChangedFocus = true;
  var editable;
  var autofocus;
  var emailValidation;

  MyTextInput(this.labelText,
      this.controller, {
        this.textInputType = TextInputType.text,
        this.withoutBorder = false,
        this.obscureText = false,
        this.onChange = null,
        this.align = TextAlign.start,
        this.textInputAction = TextInputAction.next,
        this.focusNode,
        this.nextFocus,
        this.hint,
        this.passwordType = false,
        this.jumpToStart = true,
        this.onDone = null,
        this.editable = true,
        this.autofocus = false,
        this.emailValidation = false,
      });

  @override
  State<StatefulWidget> createState() {
    init();
    return _MyTextInputState();
  }

  init() {
    if (focusNode == null) focusNode = new FocusNode();

    if (Platform.isIOS) {
      textInputType = TextInputType.text;
    }
  }
}

class _MyTextInputState extends State<MyTextInput> {
  var _validate = false;

  @override
  void initState() {
    super.initState();
    //MARK: uncommit when debug
    //widget.focusNode.addListener(_focusNodeListener);
  }

  @override
  void dispose() {
    //MARK: uncommit when debug
    //widget.focusNode.removeListener(_focusNodeListener);
    //widget.focusNode.dispose();
    super.dispose();
  }

  Future<Null> _focusNodeListener() async {
    if (widget.focusNode.hasFocus) {
      print('TextField got the focus');
    } else {
      print('TextField lost the focus');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
        padding: EdgeInsets.all(4.0),
        child: TextField(
          textAlign: widget.align,
          obscureText: widget.obscureText,
          controller: widget.controller,
          textInputAction: widget.textInputAction,
          autofocus: widget.autofocus,
          keyboardType:
          Platform.isIOS ? TextInputType.text : widget.textInputType,
          focusNode: widget.focusNode,
          enabled: widget.editable,
          style: TextStyle(fontSize: 14.0),

          decoration: InputDecoration(
              errorText: _validate ? AppLocalizations.of(context).text(
                  "value_cant_be_empty") : null,
              labelText: widget.labelText,
              hintText: ((widget.hint == null || widget.hint.isEmpty)
                  ? AppLocalizations.of(context).text("fill_data")
                  : widget.hint),
              helperText:
              (widget.passwordType ? '8 characters required' : null),
              border: widget.withoutBorder
                  ? InputBorder.none
                  : OutlineInputBorder()),
          onSubmitted: (text) {
            widget.focusNode.unfocus();
          },
          onChanged: (t) {
            if (t.substring(0, 1) == "." &&
                t.length == 2 &&
                isNumeric(t)) {
              widget.controller.text = ("0" + widget.controller.text);
              final val = TextSelection.collapsed(
                  offset: widget.controller.text.length);
              widget.controller.selection = val;
            }
            setState(() {
              t.isEmpty ? _validate = true : _validate = false;
            });
            widget.onChange();
          },
          onEditingComplete: () {
            if (widget.onDone != null) widget.onDone();

            if (widget.nextFocus != null && widget.nextFocus is FocusNode)
              FocusScope.of(context).requestFocus(widget.nextFocus);
            else
              widget.focusNode.unfocus();
          },
        ));
  }

  bool isNumeric(String s) {
    if (s == null) {
      return false;
    }
    return double.parse(s, (e) => null) != null;
  }
}
abstract class GestureImpl {
  onVerticalDragUpdate(DragUpdateDetails details);

  onVerticalDragEnd(DragEndDetails details);

  onTap();
}

class DragTopNotification extends StatefulWidget {
  Widget child;

  DragTopNotification({Key key, @required this.child}) : super(key: key);

  @override
  _DragTopNotificationState createState() {
    return _DragTopNotificationState();
  }
}

class _DragTopNotificationState extends State<DragTopNotification>
    with SingleTickerProviderStateMixin
    implements GestureImpl {
  double _touchDy = 0.0;
  bool _draggingDown = false;
  PanelController panelController = PanelController();

  AnimationController _animationController;
  Animation _colorTween;

  NotificationManager notificationManager = NotificationManager();
  List<NotificationResponseAndroid> notifications = List();

  @override
  void initState() {
    _animationController =
        AnimationController(vsync: this, duration: Duration(milliseconds: 300));
    _colorTween = ColorTween(
            begin: Colors.transparent, end: Colors.black.withOpacity(0.6))
        .animate(_animationController);

    FirebaseDatabaseUtil().initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SlidingUpPanel(
      slideDirection: SlideDirection.DOWN,
      defaultPanelState: PanelState.CLOSED,
      minHeight: 0,
      controller: panelController,
      borderRadius: radius,
      maxHeight: (MediaQuery.of(context).size.height - 40),
      panel: _panelBody(),
      body: Center(
        child: Stack(alignment: Alignment.center, children: [
          InheritedProvider<GestureImpl>(
              inheritedData: this, child: widget.child),
          Positioned(
              top: 0.0,
              left: 0.0,
              right: 0.0,
              child: Container(
                height: (currentValAnim > 0.1 ? 1000 : 0),
                width: double.infinity,
                color: _colorTween.value,
              )),
        ]),
      ),
      onPanelSlide: animateBackground,
    );
  }

  BorderRadiusGeometry radius = BorderRadius.only(
    bottomLeft: Radius.circular(24.0),
    bottomRight: Radius.circular(24.0),
  );

  _panelBody() => Container(
      decoration: BoxDecoration(
          borderRadius: radius,
          gradient: LinearGradient(
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
              stops: [
                0.1,
                0.2,
                0.4,
                0.6,
                1
              ],
              colors: [
                Color(0xFF191B53),
                Color(0xFF001C51),
                Color(0xFF052d6c),
                Color(0xFF165595),
                Color(0xFF2087F2),
              ])),
      child: Scaffold(
          backgroundColor: Colors.transparent,
          body: Center(
            child: !panelController.isAttached || panelController.isPanelClosed
                ? Container()
                : Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: <Widget>[
                      _logoFlare().paddingOnly(
                        top: 40,
                      ),
                      Text(
                        'CENTRO NOTIFICHE',
                        style: TextStyle(
                            fontSize: 24,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ).paddingAll(25),
                      Container(
                          width: double.infinity,
                          child: Text(
                            'Elimina tutto',
                            textAlign: TextAlign.right,
                            style: TextStyle(
                                color: Colors.white,
                                fontWeight: FontWeight.bold),
                          ).addOnTapAnimation(
                              onTap: () =>
                                  notificationManager.clearNotifications())),
                      Expanded(child: _listViewNotifications()),
                      Icon(
                        Icons.drag_handle,
                        color: Colors.white,
                      ).addOnTapAnimation(
                          onTap: collapseOrExpand, animation_miliseconds: 30),
                    ],
                  ).paddingAll(8),
          )));

  Widget _logoFlare() => Container(
      height: 60,
      width: 80,
      child: FlareActor('assets/images/animated_logo.flr',
          alignment: Alignment.center,
          fit: BoxFit.fitHeight,
          animation: 'anim'));

  Widget _listViewNotifications() =>
      StreamBuilder<List<NotificationResponseAndroid>>(
        stream: notificationManager.getNotificationStream(),
        builder: (context, snapshot) {
          if (!snapshot.hasData || snapshot.data.length == 0)
            return Center(
              child: Text(
                'No notifications yet',
                style: TextStyle(
                    color: Colors.white,
                    fontWeight: FontWeight.w600,
                    fontSize: 22),
              ),
            );
          if (snapshot.hasError)
            return Center(
              child: Text('Error getting local data'),
            );

          print("data is ${snapshot.data}");
          return ListView(
            //MARK: IMPORTANT TO RETURN .map<Widget>
            children: snapshot.data
                .map<Widget>(
                  (i) => _listViewItem(i),
                )
                .toList(),
          );
        },
      );

  Widget _listViewItem(NotificationResponseAndroid notificationResponse) =>
      OnSlide(
          backgroundColor: Colors.transparent,
          items: <ActionItems>[
            new ActionItems(
                icon: Center(
                  child: Icon(
                    Icons.delete,
                    size: 30,
                    color: Colors.red,
                  ),
                ),
                onPress: () async {
                  await notificationManager
                      .removeNotification(notificationResponse.id);
                },
                backgroudColor: Colors.transparent),
          ],
          child: Card(
            margin: EdgeInsets.all(0),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(10.0),
            ),
            child: Container(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Row(
                    children: <Widget>[
                      Text(
                        "NUOVA NOTIFICA",
                        textAlign: TextAlign.left,
                        style: TextStyle(color: Colors.grey, fontSize: 10),
                      ),
                      Expanded(
                          child: Text(
                        notificationResponse.timestamp,
                        textAlign: TextAlign.right,
                        style: TextStyle(color: Colors.grey, fontSize: 10),
                      )),
                    ],
                  ).paddingOnly(left: 12, right: 12, top: 10),
                  Text(
                    notificationResponse.data.titleBg,
                    textAlign: TextAlign.left,
                    style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
                  ).paddingOnly(left: 12, right: 12, bottom: 6),
                ],
              ),
            ),
          ).paddingOnly(left: 8, right: 8, top: 14).addOnTapAnimation(
              onTap: () => NotificationHelper.onTapNotification(
                  notificationResponse, context)));

  @override
  onTap() {
    panelController.open();
  }

  @override
  onVerticalDragEnd(DragEndDetails details) {
    if (_draggingDown) {
      panelController.open();
    } else {
      panelController.close();
    }
    _touchDy = 0.0;
  }

  @override
  onVerticalDragUpdate(DragUpdateDetails details) {
    if (_touchDy < details.globalPosition.dy) {
      panelController.panelPosition = panelController.panelPosition + 0.01;
      _draggingDown = true;
    } else {
      panelController.panelPosition = panelController.panelPosition - 0.01;
      _draggingDown = false;
    }
    _touchDy = details.globalPosition.dy;
  }

  double currentValAnim = 0.0;

  animateBackground(double val) {
    try {
      if (val != null) {
        _animationController.value = val;
        setState(() {
          currentValAnim = val;
        });
      }
    } catch (e) {
      debugPrintDone;
    }
  }

  collapseOrExpand() {
    panelController.isPanelOpen
        ? panelController.close()
        : panelController.open();
  }
}

class NotificationHelper {
  static Future<Null> onTapNotification(
      NotificationResponseAndroid notificationResponse,
      BuildContext context) async {
    switch (notificationResponse.data.type.toString().toUpperCase()) {
      case NotificationType.NEWS:
        {
          NewsApi _apiNews = new NewsApi();
          List<NewsCategory> _newsList =
              await _apiNews.getNews(fromLocal: false).withProgressBar();
          _newsList.forEach((e) {
            e.news.forEach((n) {
              print(
                  'news id current = ${notificationResponse.data.newsId} , fing = ${n.id}');
              if (notificationResponse.data.newsId == n.id) {
                navigateToRouteWithArguments(
                    context: context,
                    route: newsDetailsRoute,
                    args: NewsScreenArguments(n));
                return;
              }
            });
          });
          break;
        }
      case NotificationType.EVENT:
        {
          EventsApi _apiEvent = new EventsApi();
          List<OrsiniEvent> _events =
              await _apiEvent.getEvents(fromLocal: false).withProgressBar();
          _events.forEach((e) {
            if (e.id == notificationResponse.data.eventId) {
              navigateToRouteWithArguments(
                  context: context,
                  route: EventDetailsScreen.eventDetailsRoute,
                  args: new EventScreenArguments(e));
              return;
            }
          });

          break;
        }
      case NotificationType.VIDEO:
        {
          if (notificationResponse.data != null) {
            print('DATA = ${notificationResponse.data.videoImage}');
            VideoYoutube video = new VideoYoutube(
                id: notificationResponse.data.videoId,
                image: notificationResponse.data.videoImage,
                title: notificationResponse.data.videoTitle);
            Navigator.push(
                context,
                MaterialPageRoute(
                    builder: (context) => CustomVideoBlock(videoId: video.id)));
          }
          break;
        }
      case NotificationType.AR:
        {
          HomeScreen.loadModule();
          break;
        }
      case NotificationType.EMPTY:
        {
          break;
        }
      case NotificationType.START_UP:
        {
          navigateToRouteMore(
              context: context, route: CheckoutStartup.checkoutStartup);
          break;
        }
      default:
        {
          break;
        }
    }
  }
}
class HomePresenter {
  HomeInterface _view;
  LoginManager _loginManager = LoginManager();
  NetworkManager networkManager = NetworkManager();
  SharedPreferencesManager sharedPreferencesManager =
  SharedPreferencesManager();
  HomePresenter(this._view) {
    _init();
  }

  void _init() async{

  }
  void checkLogIn() async {
    _view.showProgressBar(true);

    final RemoteConfig remoteConfig = await RemoteConfig.instance;
    final defaults = <String, dynamic>{'show_login': 'true'};
    await remoteConfig.setDefaults(defaults);

    await remoteConfig.fetch(expiration: const Duration(hours: 1));
    await remoteConfig.activateFetched();
    print('show_login' + remoteConfig.getBool('show_login').toString());

    if(! await remoteConfig.getBool('show_login')) {
      logIn('[email protected]','llbbuu');
      _view.hideLogin(true);
      _view.showProgressBar(false);
      return;
    }
    bool isAlive = await _loginManager.checkLogInToken();
    _view.showProgressBar(false);
    if(isAlive){

    }else{
      _view.goToLoginScreen();
    }
  }


  Future<bool> logIn(String email, String password) async {

    if (email==null || password==null || email.isEmpty ||
        password.isEmpty) {
      return false;
    }
    _view.showProgressBar(true);
    LoginResponse response = await networkManager.login(email, password);
    _view.showProgressBar(false);

    if (response.user != null) {
      sharedPreferencesManager.saveToken(response.user.token);
      print('autologin = ${response.user}');
      return true;
    } else {
      print('autologin = false');
      return false;
    }
  }
}
class HomePage extends StatefulWidget {
  static const String tag = "/homePage_route";

  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<HomePage> implements HomeInterface {
  HomePresenter presenter;
  final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
  final cardWidth = 110.0;
  final cardHeight = 200.0;
  bool progress = false;
  bool hideLogIn = false;
  
  @override
  void initState() {
    presenter = HomePresenter(this);
    Future.delayed(Duration(seconds: 1), () => presenter.checkLogIn());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        key: scaffoldKey,
        appBar: _appBar(),
        body: ModalProgressHUD(opacity: 0.9, dismissible: true, color: Colors.white, child: _body(), inAsyncCall: progress));
  }

  _appBar() => CustomAppBar(
        Image.asset(Images.LOGO),
        nextIconVisibility: !hideLogIn,
        nextIconData: Icons.person ,
        nextIconPress: () =>
            Navigator.of(context).push(MorpheusPageRoute(parentKey: scaffoldKey, builder: (context) => SettingsPage())) , //MARK: go to profile
      );

  _body() =>
      Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          children: <Widget>[
            Expanded(child: _menu()),
            _bottomTextContainers(),
            _bottomListView(),
          ]);
  
  _menu() => paddingAll(
        10.0,
        child: SingleChildScrollView(
          physics: BouncingScrollPhysics(),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              paddingAll(
                8.0,
                child: Text(AppLocalizations.instance.text('ventilazione'),
                    style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0, color: Colors.black54)),
              ),
              SizedBox(
                height: cardHeight,
                child: ListView(
                  scrollDirection: Axis.horizontal,
                  physics: BouncingScrollPhysics(),
                  shrinkWrap: true,
                  children: <Widget>[
                    _menuItem(AppLocalizations.of(context).text("filtri"), Images.filter, Colors.teal[700], _goToTubi),
                    _menuItem(AppLocalizations.of(context).text("diffusori"), Images.difusor, Colors.grey[400], _goToDifusori),
                    _menuItem(AppLocalizations.of(context).text("tubi_ventilazione"), Images.tube2, Colors.lightBlue[900], null),
                  ],
                ),
              ),
              paddingAll(
                8.0,
                child: Text(AppLocalizations.instance.text('aspirazione'),
                    style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0, color: Colors.black54)),
              ),
              SizedBox(
                height: cardHeight,
                child: ListView(
                  scrollDirection: Axis.horizontal,
                  physics: BouncingScrollPhysics(),
                  shrinkWrap: true,
                  children: <Widget>[
                    _menuItem(AppLocalizations.of(context).text("tubi_industiali"), Images.tube, Colors.red[600], null),
                  ],
                ),
              ),
            ],
          ),
        ),
      );

  _menuItem(String name, String image, Color borderColor, VoidCallback listener) => Card(
      elevation: 6,
      shape: RoundedRectangleBorder(
        side: BorderSide(color: borderColor, width: 2),
        borderRadius: BorderRadius.circular(15),
      ),
      margin: EdgeInsets.symmetric(vertical: 13, horizontal: 13),
      child: InkWell(
        onTap: listener,
        child: Container(
            width: cardWidth,
            child: Stack(
              children: <Widget>[
                Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Flexible(flex: 6, child: Container(child: Image.asset(image))),
                    Flexible(flex: 1, child: _divider(color: borderColor)),
                    Container(
                      height: 40,
                      child: Padding(
                        padding: const EdgeInsets.all(6.0),
                        child: Center(
                          child: AutoSizeText(
                            name,
                            minFontSize: 8.0,
                            overflow: TextOverflow.clip,
                            maxLines: 3,
                            textAlign: TextAlign.center,
                            style: TextStyle(
                              fontSize: 20.0,
                              color: Colors.black45,
                              fontStyle: FontStyle.normal,
                            ),
                          ),
                        ),
                      ),
                    )
                  ],
                ),
                listener == null
                    ? Container(
                        width: cardWidth,
                        height: cardHeight,
                        decoration: BoxDecoration(
                          color: Colors.black54,
                          borderRadius: BorderRadius.circular(15),
                        ),
                        child: Center(
                          child: paddingAll(
                            8.0,
                            child: Text(
                              AppLocalizations.of(context).text("coming_soon"),
                              textAlign: TextAlign.center,
                              style: TextStyle(color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold),
                            ),
                          ),
                        ),
                      )
                    : SizedBox(),
              ],
            )),
      ));

  _divider({Color color = Colors.teal}) {
    return new SizedBox(
      height: 10.0,
      child: new Center(
        child: new Container(
          margin: new EdgeInsetsDirectional.only(start: 6.0, end: 6.0),
          height: 2.0,
          color: color.withOpacity(0.8),
        ),
      ),
    );
  }

  _bottomTextContainers() =>
      Text(AppLocalizations.instance.text('home_le_nostre'), style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24.0, color: Colors.black54));

  _bottomListView() => Padding(
      padding: EdgeInsets.only(bottom: 6),
      child: Card(
        elevation: 4,
        shape: RoundedRectangleBorder(),
        child: Container(
          height: 70.0,
          child: ListView(
            scrollDirection: Axis.horizontal,
            children: <Widget>[
              _returnImage(Images.mastersan),
              _returnImage(Images.plenusan),
              _returnImage(Images.filtrasan),
              _returnImage(Images.sanitized),
              _returnImage(Images.SERTEFICAT_4),
              _returnImage(Images.SERTEFICAT_5),
              _returnImage(Images.SERTEFICAT_3),
              _returnImage(Images.SERTEFICAT_6),
            ],
          ),
        ),
      ));

  _returnImage(String image) => paddingAll(12,
      child: GestureDetector(
          onTap: () {
            Navigator.of(context).push(MorpheusPageRoute(
                parentKey: scaffoldKey,
                builder: (_) => Scaffold(
                      appBar: CustomAppBar(
                        Image.asset(Images.LOGO),
                        nextIconVisibility: false,
                        backIconVisibility: true,
                        backIconPress: () => Navigator.of(context).pop(), //MARK: go to profile
                      ),
                      body: WebView(
                          gestureNavigationEnabled: true,
                          initialUrl: 'https://www.tecnicasrl.it/certificazioni-aziendali/',
                          javascriptMode: JavascriptMode.unrestricted,
                          onWebViewCreated: (WebViewController webViewController) {}),
                    )));
          },
          child: new Image.asset(
            image,
            fit: BoxFit.cover,
          )));

  _goToTubi() {
    Navigator.of(context).pushNamed(ListaPage.tag);
  }

  _goToDifusori() {
    Navigator.of(context).pushNamed(FilterDifusoriPage.tag);
  }

  @override
  void goToLoginScreen() {
    Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.tag, (Route<dynamic> route) => false);
  }

  @override
  void showSnack(String s) {
    final action = SnackBarAction(
      label: "OK",
      onPressed: () {
        scaffoldKey.currentState.removeCurrentSnackBar();
      },
    );
    scaffoldKey.currentState.showSnackBar(new SnackBar(
      content: new Text(s),
      action: action,
    ));
  }

  @override
  void hideLogin(bool hide) {
   setState(() {
     hideLogIn = hide;
   });
  }

  @override
  void showProgressBar(bool visability) {
    setState(() {
      progress = visability;
    });
  }

}
class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {
  Locale language = Locale('it', '');
  AppLocalizationsDelegate appLocalizationDelegate =
      AppLocalizationsDelegate(Locale('it', ''));
  SharedPreferencesManager _sharedPreferencesManager = SharedPreferencesManager();

  final routes = <String, WidgetBuilder>{
    ListaPage.tag: (_) => ListaPage(),
    FiltriListDetailPage.tag: (_) => FiltriListDetailPage(),
    DiffusoreDetailPage.tag: (_) => DiffusoreDetailPage(),
    ListaDifusorePage.tag: (_) => ListaDifusorePage(),
    FilterDifusoriPage.tag: (_) => FilterDifusoriPage(),
    SchedaDiffusorePage.tag: (_) => SchedaDiffusorePage(),
    PersoPasswordPage.tag: (_) => PersoPasswordPage(),
    RegistrationPage.tag: (_) => RegistrationPage(),
    HomePage.tag: (_) => HomePage(),
    SettingsPage.tag: (_) => SettingsPage(),
    LoginPage.tag: (_) => LoginPage(),
  };

  @override
  void initState() {
    getLanguage().then((lang) {
      setState(() {
        appLocalizationDelegate = AppLocalizationsDelegate(lang);
        language = lang;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      routes: routes,
      builder: (context, child) {
        return MediaQuery(
          child: child,
          data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
        );
      },
      theme: ThemeData(
        brightness: Brightness.light,
        primaryColor: Colors.grey[400],
        scaffoldBackgroundColor: Colors.grey[200],
        accentColor: Colors.red[600],
        fontFamily: 'Montserrat',
        textTheme: TextTheme(
          headline: TextStyle(fontSize: 72.0, fontWeight: FontWeight.bold),
          title: TextStyle(fontSize: 36.0, fontStyle: FontStyle.italic),
          body1: TextStyle(fontSize: 14.0, fontFamily: 'Hind'),
        ),
      ),
      onGenerateRoute: (settings) {
        switch (settings.name) {
          case ListaPage.tag:
            return MorpheusPageRoute(
              builder: (_) => ListaPage(),
              settings: settings,
            );
            break;
          case FiltriListDetailPage.tag:
            return MorpheusPageRoute(
              builder: (_) => FiltriListDetailPage(),
              settings: settings,
            );
            break;
          case DiffusoreDetailPage.tag:
            return MorpheusPageRoute(
              builder: (_) => DiffusoreDetailPage(),
              settings: settings,
            );
            break;
          case LoginPage.tag:
            return MorpheusPageRoute(
              builder: (_) => LoginPage(),
              settings: settings,
            );
            break;
          case FilterDifusoriPage.tag:
            return MorpheusPageRoute(
              builder: (_) => FilterDifusoriPage(),
              settings: settings,
            );
            break;
          case ListaDifusorePage.tag:
            return MorpheusPageRoute(
              builder: (_) => ListaDifusorePage(),
              settings: settings,
            );
            break;
          case SchedaDiffusorePage.tag:
            return MorpheusPageRoute(
              builder: (_) => SchedaDiffusorePage(),
              settings: settings,
            );
            break;
          case PersoPasswordPage.tag:
            return MorpheusPageRoute(
              builder: (_) => PersoPasswordPage(),
              settings: settings,
            );
            break;
          case RegistrationPage.tag:
            return MorpheusPageRoute(
              builder: (_) => RegistrationPage(),
              settings: settings,
            );
            break;
          case HomePage.tag:
            return MorpheusPageRoute(
              builder: (_) => HomePage(),
              settings: settings,
            );
          case SettingsPage.tag:
            return MorpheusPageRoute(
              builder: (_) => SettingsPage(),
              settings: settings,
            );
            break;
          case '/':
          default:
            return MorpheusPageRoute(
              builder: (_) => HomePage(),
              settings: settings,
            );
            break;
        }
      },
      localizationsDelegates: [
        appLocalizationDelegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [
        const Locale('it', ''),
        const Locale('en', ''),
      ],
      localeResolutionCallback:
          (Locale locale, Iterable<Locale> supportedLocales) {
        return locale;
      },
      locale: language,
      home: HomePage(),
    );
  }

  Future<Locale> getLanguage() async {
    AppLocalizations l;
    await _sharedPreferencesManager.init();
    final isIt = await _sharedPreferencesManager.getDeffaultLanguageState(
        _sharedPreferencesManager.IS_DEFFAULT_LANGUAGE);
    //HelperView.toast("main localization " + isIt.toString());
    if (isIt) {
      var lang = const Locale('it', '');
      l = await AppLocalizations.instance.load(lang);
    } else {
      var lang = const Locale('en', '');
      l = await AppLocalizations.instance.load(lang);
    }

    return l.locale;
  }
}
class NetworkManager {
  String _locale = "IT";
  static final String DOMEN = 'http://tecnica.bizonoff-dev.net';
  CHttp chttp = CHttp();
  SharedPreferencesManager _sharedPreferencesManager = SharedPreferencesManager();

  static final NetworkManager _singleton = new NetworkManager._internal();

  factory NetworkManager() {
    return _singleton;
  }

  NetworkManager._internal() {
    _getLocalization();
  }

  _getLocalization() async {
    final isIt = await _sharedPreferencesManager.getDeffaultLanguageState(_sharedPreferencesManager.IS_DEFFAULT_LANGUAGE);
    if (isIt) {
      _locale = "IT";
    } else {
      _locale = "EN";
    }
    print("Ntwork manager locale: $_locale");
  }

  Future<GetFiltryResponse> getFiltri(String eniso, String ceen, String search_field, String sanitizing, bool forceUpdate) async {
    //MARK: response url
    var url = DOMEN + '/api/get-filtri';

    var query = jsonEncode({
      "lang": _locale,
    });
    var response = await http.post(url,
        body: {
          "data": query,
        },
        headers: {
          "Authorization": "Bearer " + await _sharedPreferencesManager.getToken(),
        });
    var responseJson = new GetFiltryResponse.fromJson(json.decode(response.body));
    print(responseJson);
    return responseJson;
  }

  Future<GetCategoryResponse> getCategory(String cod_famiglia, String search_field, bool forceUpdate) async {
    //MARK: url
    var url = DOMEN + '/api/get-category';
    
    var query = jsonEncode({
      "cod_famiglia": cod_famiglia,
      "search_field": search_field,
      "lang": _locale,
    });
    var response = await http.post(url,
        body: {
          "data": query,
        },
        headers: {
          "Authorization": "Bearer " + await _sharedPreferencesManager.getToken(),
        });
    print(response);
    var responseJson = new GetCategoryResponse.fromJson(json.decode(response.body));
    print(responseJson);
    return responseJson;
  }

  Future<GetArticleResponse> getArticle(String cod_categoria, String cod_famiglia, String search_field, bool forceUpdate) async {
    //MARK: url
    var url = DOMEN + '/api/get-article';

    var query = jsonEncode({"cod_categoria": cod_categoria, "cod_famiglia": cod_famiglia, "search_field": search_field, "lang": _locale});
    var response = await http.post(url,
        body: {
          "data": query,
        },
        headers: {
          "Authorization": "Bearer " + await _sharedPreferencesManager.getToken(),
        });
    print(response);
    var responseJson = new GetArticleResponse.fromJson(json.decode(response.body));
    print(responseJson);
    return responseJson;
  }

  Future<CharacteristicResponse> getCharacteristic(
      String cod_categoria, String cod_articolo, String portata, String diff_temp, String velocita, String altezza, bool forceUpdate) async {
    //MARK: url
    var url = DOMEN + '/api/get-characteristics';
    
    var query = jsonEncode({
      "cod_categoria": cod_categoria,
      "cod_articolo": cod_articolo,
      "portata": portata,
      "diff_temp": diff_temp,
      "velocita": velocita,
      "altezza": altezza,
      "lang": _locale
    });
    var response = await http.post(url,
        body: {
          "data": query,
        },
        headers: {
          "Authorization": "Bearer " + await _sharedPreferencesManager.getToken(),
        });
    print(response);
    CharacteristicResponse responseJson = new CharacteristicResponse.fromJson(json.decode(response.body));
    return responseJson;
  }

  Future<GetFamigliaResponse> getFamiglia(bool forceUpdate) async {
    //MARK: url
    var url = DOMEN + '/api/get-famiglia';

    await _getLocalization();

    var query = jsonEncode({"lang": _locale});
    var response = await http.post(url,
        body: {
          "data": query,
        },
        headers: {
          "Authorization": "Bearer " + await _sharedPreferencesManager.getToken(),
        });
    print(response);
    var responseJson = new GetFamigliaResponse.fromJson(json.decode(response.body));
    print(responseJson);
    return responseJson;
  }

  Future<profile_info.GetProfileResponse> getProfileInformation() async {
    //MARK: url
    var url = DOMEN + '/api/get-profile';
    var response = await http.post(url, headers: {
      "Authorization": "Bearer " + await _sharedPreferencesManager.getToken(),
    }).catchError((Object error) {
      print(error);
    });
    print(response);
    var responseJson = new profile_info.GetProfileResponse.fromJson(json.decode(response.body));
    print(responseJson);
    return responseJson;
  }

  Future<UpdateProfileResponse> updateProfileInfo(profile_info.User user) async {
    var url = DOMEN + '/api/update-profile';
    var token = await _sharedPreferencesManager.getToken();
    await _getLocalization();
    var response = await http.post(url, headers: {
      "Authorization": "Bearer " + token
    }, body: {
      "name": user.name,
      "surname": user.surname,
      "company": user.company,
      "lang": _locale,
      "city": user.city,
      "country": user.country,
    }).catchError((Object error) {
      print(error.toString());
    });
    print(response.toString());
    var responseJson = new UpdateProfileResponse.fromJson(json.decode(response.body));
    print(responseJson);
    return responseJson;
  }

  Future<RegistrationResponse> registration(profile_info.User user, String password) async {
    var url = DOMEN + '/api/registration';

    Codec<String, String> stringToBase64 = utf8.fuse(base64);
    String encoded = stringToBase64.encode(password);

    await _getLocalization();

    var response = await http.post(url, headers: {
      "Accept": "application/json",
      "Content-Type": "application/x-www-form-urlencoded",
    }, body: {
      "name": user.name,
      "email": user.email,
      "surname": user.surname,
      "company": user.company,
      "password": password,
      "lang": _locale,
      "city": user.city,
      "country": user.country,
    }).catchError((Object error) {
      print(error.toString());
    });
    print(response.toString());
    var responseJson = RegistrationResponse.fromJson(json.decode(response.body));
    print(responseJson);
    return responseJson;
  }

  Future<LoginResponse> login(String email, String password) async {
    var url = DOMEN + '/api/login';
    Codec<String, String> stringToBase64 = utf8.fuse(base64);
    String encoded = stringToBase64.encode(password);
    var response = await http.post(
      url,
      body: {"password": encoded, "email": email},
    );
    print(response.body);

    var responseJson = new LoginResponse.fromJson(json.decode(response.body));
    print(responseJson);

    return responseJson;
  }

  Future<String> forgotPassword(String email) async {
    var url = DOMEN + '/api/restore-password';
    var response = await http.post(
      url,
      body: {"email": email},
    );
    print(response.body);

    return json.decode(response.body)["status"];
  }

  Future<bool> checkToken() async {
    var url = DOMEN + '/api/ttl';
    var token = await _sharedPreferencesManager.getToken();
    var response = await http.post(url, headers: {
      "Accept": "application/json",
      "Content-Type": "application/x-www-form-urlencoded",
      "Authorization": "Bearer " + token,
    });
    print(response.body);

    bool responseJson = false;
    try {
      responseJson = json.decode(response.body)['valid'];
    } catch (e) {
      print("checkToken $e");
    }
    return responseJson;
  }

  Future<void> sendPdf(String email, String type,
      {String article, String portata, String diff_temp, String velocita, String altezza, String code}) async {
    //type = difusor и filter // графа parametres используеться только для дифузоров
    var url = DOMEN + '/api/send-email';
    var token = await _sharedPreferencesManager.getToken();

    await _getLocalization();

    var query = (jsonEncode({"article": article, "portata": portata, "diff_temp": diff_temp, "velocita": velocita, "altezza": altezza, "code": code})
        .toString());

    var response = await http.post(url, headers: {
      "Accept": "application/json",
      "Content-Type": "application/x-www-form-urlencoded",
      "Authorization": "Bearer " + token,
    }, body: {
      "lang": _locale,
      "type": type,
      "id": code,
      "email": email,
      "parametres": query
    });

    print("sendPdf " + response.body);
  }
}

class CHttp {
  Dio dio = Dio();

  CHttp() {
    _init();
  }

  _init() {
    dio.interceptors.add(DioCacheManager(CacheConfig(baseUrl: NetworkManager.DOMEN)).interceptor);
  }

  Future<Response<dynamic>> getUrl(String url, {headers, body, bool forceUpdate = false}) async {
    var response;
    if (body == null) {
       response = await dio.get(url,
         options: buildCacheOptions(Duration(hours: 1),forceRefresh:forceUpdate,options: Options(
           headers:headers, ),),);
      return response;
    } else {
      response = await dio.post(url,
        data: body,
          options: buildCacheOptions(Duration(hours: 1),forceRefresh:forceUpdate,options: Options(
    headers:headers, ),),);
      return response;
    }
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment