From c307ed88b65df3d3d2f486ae8faa10b20c341ba6 Mon Sep 17 00:00:00 2001 From: Frederik Benoist Date: Sun, 26 Feb 2023 17:29:42 +0100 Subject: [PATCH] refonte homepage from wishlist --- lib/model/wishlist_model.dart | 58 +- .../product_detail/product_detail.dart | 2 + lib/ui/home/tab_home.dart | 1104 +++-------------- macos/Podfile.lock | 44 + macos/Runner.xcodeproj/project.pbxproj | 62 +- .../contents.xcworkspacedata | 3 + 6 files changed, 319 insertions(+), 954 deletions(-) create mode 100644 macos/Podfile.lock diff --git a/lib/model/wishlist_model.dart b/lib/model/wishlist_model.dart index 7b32f47..15a3a85 100644 --- a/lib/model/wishlist_model.dart +++ b/lib/model/wishlist_model.dart @@ -10,11 +10,13 @@ class WishlistModel { late int sale; late int stock; late String location; + late int photo; WishlistModel( {required this.id, required this.name, required this.price, + required this.photo, required this.image, required this.rating, required this.review, @@ -26,28 +28,21 @@ class WishlistModel { List wishlistData = [ WishlistModel( id: 1, - name: 'IWO 8 Smart Watch Apple iWatch Mirror For Android iPhone', + name: "Villeneuve d'asc ONE-STEP", price: 62, - image: GLOBAL_URL + '/apps/ecommerce/product/46.jpg', + photo: 1, + image: + 'https://mp4.ikksgroup.com/photos/1/0/1/8/4/4/101844-thumbnail.JPG', rating: 5, review: 42, - sale: 69, + sale: 4, stock: 5, - location: 'Brooklyn'), + location: "Villeneuve d'asc"), WishlistModel( id: 2, - name: 'Asus Rog Phone 3 Rogphone III Ram 12Gb 512Gb Snapdragon 865+ Plus', - price: 1152, - image: GLOBAL_URL + '/apps/ecommerce/product/48.jpg', - rating: 5, - review: 1, - sale: 2, - stock: 22, - location: 'Brooklyn'), - WishlistModel( - id: 3, name: 'BARDI Smart PLUG WiFi Wireless Colokan - IoT Smart Home', price: 11.46, + photo: 2, image: GLOBAL_URL + '/apps/ecommerce/product/69.jpg', rating: 5, review: 1062, @@ -55,45 +50,14 @@ List wishlistData = [ stock: 0, location: 'Brooklyn'), WishlistModel( - id: 4, + id: 3, name: 'ipad Pro 2020 11-inch 128GB Wi-Fi Only - Silver', price: 866, + photo: 3, image: GLOBAL_URL + '/apps/ecommerce/product/49.jpg', rating: 5, review: 22, sale: 468, stock: 25, location: 'Brooklyn'), - WishlistModel( - id: 5, - name: 'Fimi X8 SE Black', - price: 567, - image: GLOBAL_URL + '/apps/ecommerce/product/26.jpg', - rating: 5, - review: 63, - sale: 115, - stock: 0, - location: 'Brooklyn', - ), - WishlistModel( - id: 6, - name: - 'Xiaomi Air Purifier 3 Mijia OLED Touch Sterilization Air Ionizer - 3', - price: 139, - image: GLOBAL_URL + '/apps/ecommerce/product/33.jpg', - rating: 5, - review: 275, - sale: 1055, - stock: 4, - location: 'Brooklyn'), - WishlistModel( - id: 7, - name: 'Delta Boots Import 8 Inch', - price: 18.3, - image: GLOBAL_URL + '/apps/ecommerce/product/25.jpg', - rating: 5, - review: 212, - sale: 735, - stock: 55, - location: 'Brooklyn') ]; diff --git a/lib/ui/general/product_detail/product_detail.dart b/lib/ui/general/product_detail/product_detail.dart index 3ce69e7..ad3f03b 100644 --- a/lib/ui/general/product_detail/product_detail.dart +++ b/lib/ui/general/product_detail/product_detail.dart @@ -21,6 +21,7 @@ class ProductDetailPage extends StatefulWidget { final String name; final String image; final double price; + final int photo; final double rating; final int review; final int sale; @@ -30,6 +31,7 @@ class ProductDetailPage extends StatefulWidget { this.name = '', this.image = '', this.price = 24, + this.photo = 1, this.rating = 4, this.review = 45, this.sale = 63}) diff --git a/lib/ui/home/tab_home.dart b/lib/ui/home/tab_home.dart index 875cb6e..a1d5be4 100644 --- a/lib/ui/home/tab_home.dart +++ b/lib/ui/home/tab_home.dart @@ -1,35 +1,18 @@ /* -For this homepage, appBar is created at the bottom after CustomScrollView +This is home page we used AutomaticKeepAliveClientMixin to keep the state when moving from 1 navbar to another navbar, so the page is not refresh overtime */ -import 'dart:async'; - -import 'package:carousel_slider/carousel_slider.dart'; -import 'package:mobdr/model/category_for_you_model.dart'; -import 'package:mobdr/model/category_model.dart'; -import 'package:mobdr/model/flashsale_model.dart'; -import 'package:mobdr/model/home_banner_model.dart'; -import 'package:mobdr/model/home_trending_model.dart'; -import 'package:mobdr/model/last_search_model.dart'; -import 'package:mobdr/model/recomended_product_model.dart'; +import 'package:mobdr/config/constant.dart'; +import 'package:mobdr/config/global_style.dart'; +import 'package:mobdr/model/wishlist_model.dart'; import 'package:mobdr/ui/general/chat_us.dart'; import 'package:mobdr/ui/general/notification.dart'; import 'package:mobdr/ui/general/product_detail/product_detail.dart'; -import 'package:mobdr/ui/home/coupon.dart'; -import 'package:mobdr/ui/home/flashsale.dart'; -import 'package:mobdr/ui/home/last_search.dart'; -import 'package:mobdr/ui/home/product_category.dart'; -import 'package:mobdr/ui/home/search.dart'; -import 'package:mobdr/ui/home/search_product.dart'; import 'package:mobdr/ui/reusable/reusable_widget.dart'; import 'package:mobdr/ui/reusable/cache_image_network.dart'; -import 'package:mobdr/ui/reusable/global_function.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:mobdr/config/constant.dart'; -import 'package:mobdr/config/global_style.dart'; class TabHomePage extends StatefulWidget { @override @@ -37,43 +20,12 @@ class TabHomePage extends StatefulWidget { } class _TabHomePageState extends State - with TickerProviderStateMixin, AutomaticKeepAliveClientMixin { + with AutomaticKeepAliveClientMixin { // initialize global function and reusable widget - final _globalFunction = GlobalFunction(); final _reusableWidget = ReusableWidget(); - int _currentImageSlider = 0; - - late ScrollController _scrollController; - Color _topIconColor = Colors.white; - Color _topSearchColor = Colors.white; - late AnimationController _topColorAnimationController; - late Animation _appBarColor; - SystemUiOverlayStyle _appBarSystemOverlayStyle = SystemUiOverlayStyle.light; - - Timer? _flashsaleTimer; - late int _flashsaleSecond; - - void _startFlashsaleTimer() { - const period = const Duration(seconds: 1); - _flashsaleTimer = Timer.periodic(period, (timer) { - setState(() { - _flashsaleSecond--; - }); - if (_flashsaleSecond == 0) { - _cancelFlashsaleTimer(); - Fluttertoast.showToast( - msg: 'Flash sale is over', toastLength: Toast.LENGTH_LONG); - } - }); - } - - void _cancelFlashsaleTimer() { - if (_flashsaleTimer != null) { - _flashsaleTimer?.cancel(); - _flashsaleTimer = null; - } - } + // _listKey is used for AnimatedList + final GlobalKey _listKey = GlobalKey(); // keep the state to do not refresh when switch navbar @override @@ -81,888 +33,228 @@ class _TabHomePageState extends State @override void initState() { - _setupAnimateAppbar(); - - // set how many times left for flashsale - var timeNow = DateTime.now(); - - // 8000 second = 2 hours 13 minutes 20 second for flashsale timer - var flashsaleTime = - timeNow.add(Duration(seconds: 8000)).difference(timeNow); - _flashsaleSecond = flashsaleTime.inSeconds; - _startFlashsaleTimer(); - super.initState(); } @override void dispose() { - _scrollController.dispose(); - _topColorAnimationController.dispose(); - - _cancelFlashsaleTimer(); super.dispose(); } - void _setupAnimateAppbar() { - // use this function and paramater to animate top bar - _topColorAnimationController = - AnimationController(vsync: this, duration: Duration(seconds: 0)); - _appBarColor = ColorTween(begin: Colors.transparent, end: Colors.white) - .animate(_topColorAnimationController); - _scrollController = ScrollController() - ..addListener(() { - _topColorAnimationController.animateTo(_scrollController.offset / 120); - // if scroll for above 150, then change app bar color to white, search button to dark, and top icon color to dark - // if scroll for below 150, then change app bar color to transparent, search button to white and top icon color to light - if (_scrollController.hasClients && - _scrollController.offset > (150 - kToolbarHeight)) { - if (_topIconColor != BLACK_GREY) { - _topIconColor = BLACK_GREY; - _topSearchColor = Colors.grey[100]!; - _appBarSystemOverlayStyle = SystemUiOverlayStyle.dark; - } - } else { - if (_topIconColor != Colors.white) { - _topIconColor = Colors.white; - _topSearchColor = Colors.white; - _appBarSystemOverlayStyle = SystemUiOverlayStyle.light; - } - } - }); - } - @override Widget build(BuildContext context) { // if we used AutomaticKeepAliveClientMixin, we must call super.build(context); super.build(context); - - final double boxImageSize = (MediaQuery.of(context).size.width / 3); - final double categoryForYouHeightShort = boxImageSize; - final double categoryForYouHeightLong = (boxImageSize * 2); - + final double boxImageSize = (MediaQuery.of(context).size.width / 4); return Scaffold( - body: Stack( - children: [ - CustomScrollView( - controller: _scrollController, - slivers: [ - SliverList( - delegate: SliverChildListDelegate([ - _createHomeBannerSlider(), - _createCoupon(), - _createGridCategory(), - Container( - margin: EdgeInsets.only(top: 10, left: 16, right: 16), - child: Text('Flash Sale', style: GlobalStyle.sectionTitle), - ), - Container( - margin: EdgeInsets.only(top: 4, left: 16, right: 16), - child: Row( - children: [ - Text('Flash sale end in ', - style: TextStyle( - fontWeight: FontWeight.normal, - fontSize: 13, - color: CHARCOAL)), - _buildFlashsaleTime(), - Expanded( - child: GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => FlashSalePage( - seconds: _flashsaleSecond))); - }, - child: Text('View All', - style: GlobalStyle.viewAll, - textAlign: TextAlign.end), - ), - ) - ], - ), - ), - Container( - margin: EdgeInsets.only(top: 16), - height: boxImageSize * - GlobalStyle.horizontalProductHeightMultiplication, - child: ListView.builder( - padding: EdgeInsets.only(left: 12, right: 12), - scrollDirection: Axis.horizontal, - itemCount: flashsaleData.length, - itemBuilder: (BuildContext context, int index) { - return _buildFlashsaleCard(index, boxImageSize); - }, - ), - ), - Container( - margin: EdgeInsets.only(top: 30, left: 16, right: 16), - child: - Text('Trending Product', style: GlobalStyle.sectionTitle), - ), - Container( - margin: EdgeInsets.fromLTRB(12, 0, 12, 0), - child: GridView.count( - padding: EdgeInsets.fromLTRB(0, 8, 0, 0), - primary: false, - childAspectRatio: 4 / 1.6, - shrinkWrap: true, - crossAxisSpacing: 2, - mainAxisSpacing: 2, - crossAxisCount: 2, - children: List.generate(homeTrendingData.length, (index) { - return _buildTrendingProductCard(index); - }), - ), - ), - Container( - margin: EdgeInsets.only(top: 30, left: 16, right: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text('Last Search', style: GlobalStyle.sectionTitle), - GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => LastSearchPage())); - }, - child: Text('View All', - style: GlobalStyle.viewAll, - textAlign: TextAlign.end), - ) - ], - ), - ), - Container( - margin: EdgeInsets.only(top: 16), - height: boxImageSize * - GlobalStyle.horizontalProductHeightMultiplication, - child: ListView.builder( - padding: EdgeInsets.only(left: 12, right: 12), - scrollDirection: Axis.horizontal, - itemCount: lastSearchData.length, - itemBuilder: (BuildContext context, int index) { - return _buildLastSearchCard(index, boxImageSize); - }, - ), - ), - Container( - margin: EdgeInsets.only(top: 30, left: 16, right: 16), - child: - Text('Category For You', style: GlobalStyle.sectionTitle), - ), - _createCategoryForYou(boxImageSize, categoryForYouHeightShort, - categoryForYouHeightLong), - Container( - margin: EdgeInsets.only(top: 30, left: 16, right: 16), - child: Text('Recomended Product', - style: GlobalStyle.sectionTitle), - ), - CustomScrollView( - shrinkWrap: true, - primary: false, - slivers: [ - SliverPadding( - padding: EdgeInsets.fromLTRB(12, 8, 12, 8), - sliver: SliverGrid( - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - mainAxisSpacing: 8, - crossAxisSpacing: 8, - childAspectRatio: GlobalStyle.gridDelegateRatio, - ), - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - return _buildRecomendedProductCard(index); - }, - childCount: recomendedProductData.length, - ), - ), - ), - ]), - ])), - ], + appBar: AppBar( + automaticallyImplyLeading: false, + elevation: GlobalStyle.appBarElevation, + title: Text( + 'Bonjour, Frédérik', + style: GlobalStyle.appBarTitle, ), - // Create AppBar with Animation - Container( - height: AppBar().preferredSize.height + - MediaQuery.of(context).padding.top - - 20 + - 22, - child: AnimatedBuilder( - animation: _topColorAnimationController, - builder: (context, child) => AppBar( - automaticallyImplyLeading: false, - backgroundColor: _appBarColor.value, - systemOverlayStyle: _appBarSystemOverlayStyle, - elevation: GlobalStyle.appBarElevation, - title: Container( - child: TextButton( - style: ButtonStyle( - backgroundColor: - MaterialStateProperty.resolveWith( - (Set states) => _topSearchColor, - ), - overlayColor: - MaterialStateProperty.all(Colors.transparent), - shape: MaterialStateProperty.all(RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5.0), - )), - ), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SearchPage())); - }, - child: Row( - children: [ - SizedBox(width: 8), - Icon( - Icons.search, - color: Colors.grey[500], - size: 18, - ), - SizedBox(width: 8), - Text( - 'Search Product a', - style: TextStyle( - color: Colors.grey[500], - fontWeight: FontWeight.normal), - ) - ], - )), - ), - actions: [ - GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ChatUsPage())); - }, - child: Icon(Icons.email, color: _topIconColor)), - IconButton( - icon: _reusableWidget.customNotifIcon( - count: 8, notifColor: _topIconColor), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => NotificationPage())); - }), - ], - ), - ), - ) - ], - ), - ); - } - - Widget _createHomeBannerSlider() { - return Column( - children: [ - CarouselSlider( - items: homeBannerData - .map((item) => Container( - child: buildCacheNetworkImage( - width: 0, height: 0, url: item.image), - )) - .toList(), - options: CarouselOptions( - aspectRatio: 8 / 6, - viewportFraction: 1.0, - autoPlay: true, - autoPlayInterval: Duration(seconds: 6), - autoPlayAnimationDuration: Duration(milliseconds: 300), - enlargeCenterPage: false, - onPageChanged: (index, reason) { - setState(() { - _currentImageSlider = index; - }); - }), - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: homeBannerData.map((item) { - int index = homeBannerData.indexOf(item); - return Container( - width: 8.0, - height: 8.0, - margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: _currentImageSlider == index - ? PRIMARY_COLOR - : Colors.grey[300], - ), - ); - }).toList(), - ), - ], - ); - } - - Widget _createCoupon() { - return GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: () { - Navigator.push( - context, MaterialPageRoute(builder: (context) => CouponPage())); - }, - child: Container( - padding: EdgeInsets.all(12), - margin: EdgeInsets.all(16.0), - decoration: BoxDecoration( - color: SOFT_BLUE, borderRadius: BorderRadius.circular(5)), - child: Row( - children: [ - Expanded( - child: Container( - child: Text( - 'There are 10 coupon waiting', - style: TextStyle( - fontSize: 14, - color: Color(0xffffffff), - fontWeight: FontWeight.bold), - ), - ), - ), - Icon(Icons.local_offer, color: Colors.white) + backgroundColor: GlobalStyle.appBarBackgroundColor, + systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle, + actions: [ + GestureDetector( + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (context) => ChatUsPage())); + }, + child: Icon(Icons.email, color: BLACK_GREY)), + IconButton( + icon: _reusableWidget.customNotifIcon( + count: 8, notifColor: BLACK_GREY), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => NotificationPage())); + }), ], ), - ), - ); - } - - Widget _buildFlashsaleTime() { - int hour = _flashsaleSecond ~/ 3600; - int minute = _flashsaleSecond % 3600 ~/ 60; - int second = _flashsaleSecond % 60; - - return Row( - children: [ - Container( - padding: EdgeInsets.fromLTRB(3, 4, 3, 4), - decoration: BoxDecoration( - color: Colors.red, borderRadius: BorderRadius.circular(5)), // - child: Text(_globalFunction.formatTime(hour), - style: TextStyle( - color: Colors.white, - fontSize: 13, - fontWeight: FontWeight.bold)), - ), - Text(' : ', - style: TextStyle( - color: Colors.red, fontSize: 13, fontWeight: FontWeight.bold)), - Container( - padding: EdgeInsets.fromLTRB(3, 4, 3, 4), - decoration: BoxDecoration( - color: Colors.red, borderRadius: BorderRadius.circular(5)), // - child: Text(_globalFunction.formatTime(minute), - style: TextStyle( - color: Colors.white, - fontSize: 13, - fontWeight: FontWeight.bold)), - ), - Text(' : ', - style: TextStyle( - color: Colors.red, fontSize: 13, fontWeight: FontWeight.bold)), - Container( - padding: EdgeInsets.fromLTRB(3, 4, 3, 4), - decoration: BoxDecoration( - color: Colors.red, borderRadius: BorderRadius.circular(5)), // - child: Text(_globalFunction.formatTime(second), - style: TextStyle( - color: Colors.white, - fontSize: 13, - fontWeight: FontWeight.bold)), - ) - ], - ); - } - - Widget _createGridCategory() { - return GridView.count( - padding: EdgeInsets.fromLTRB(16, 16, 16, 0), - primary: false, - childAspectRatio: 1.1, - shrinkWrap: true, - crossAxisSpacing: 0, - mainAxisSpacing: 0, - crossAxisCount: 4, - children: List.generate(categoryData.length, (index) { - return GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ProductCategoryPage( - categoryId: categoryData[index].id, - categoryName: categoryData[index].name))); - }, - child: Column(children: [ - buildCacheNetworkImage( - width: 40, - height: 40, - url: categoryData[index].image, - plColor: Colors.transparent), - Flexible( - child: Container( - margin: EdgeInsets.fromLTRB(0, 10, 0, 0), - child: Text( - categoryData[index].name, - style: TextStyle( - color: CHARCOAL, - fontWeight: FontWeight.normal, - fontSize: 12, - ), - textAlign: TextAlign.center, - ), - ), - ) - ])); - }), - ); - } - - Widget _buildFlashsaleCard(index, boxImageSize) { - return Container( - width: boxImageSize + 10, - child: Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - elevation: 2, - color: Colors.white, - child: GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ProductDetailPage( - name: flashsaleData[index].name, - image: flashsaleData[index].image, - price: flashsaleData[index].price, - rating: 4, - review: 45, - sale: flashsaleData[index].sale))); + body: AnimatedList( + key: _listKey, + initialItemCount: wishlistData.length, + physics: AlwaysScrollableScrollPhysics(), + itemBuilder: (context, index, animation) { + return _buildWishlistCard( + wishlistData[index], boxImageSize, animation, index); }, - child: Column( - children: [ - Stack( - children: [ - ClipRRect( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(10), - topRight: Radius.circular(10)), - child: buildCacheNetworkImage( - width: boxImageSize + 10, - height: boxImageSize + 10, - url: flashsaleData[index].image)), - Positioned( - right: 0, - top: 10, - child: Container( - decoration: BoxDecoration( - color: Colors.red, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(6), - bottomLeft: Radius.circular(6))), - padding: EdgeInsets.fromLTRB(8, 4, 8, 4), - child: Text( - flashsaleData[index].discount.toString() + '%', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 12)), - ), - ) - ], - ), - Container( - margin: EdgeInsets.fromLTRB(8, 8, 8, 8), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - flashsaleData[index].name, - style: GlobalStyle.productName, - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - Container( - margin: EdgeInsets.only(top: 5), - child: Text( - '\$ ' + - _globalFunction.removeDecimalZeroFormat( - flashsaleData[index].price), - style: GlobalStyle.productPriceDiscounted), - ), - Container( - margin: EdgeInsets.only(top: 2), - child: Text( - '\$ ' + - _globalFunction.removeDecimalZeroFormat( - ((100 - flashsaleData[index].discount) * - flashsaleData[index].price / - 100)), - style: GlobalStyle.productPrice), - ) - ], - ), - ) - ], - ), - ), - ), - ); + )); } - Widget _buildTrendingProductCard(index) { - return GestureDetector( - onTap: () { - StatefulWidget menuPage = - SearchProductPage(words: homeTrendingData[index].name); - Navigator.push( - context, MaterialPageRoute(builder: (context) => menuPage)); - }, - child: Card( + Widget _buildWishlistCard( + WishlistModel wishlistData, boxImageSize, animation, index) { + return SizeTransition( + sizeFactor: animation, + child: Container( + margin: EdgeInsets.fromLTRB(12, 6, 12, 0), + child: Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), elevation: 2, color: Colors.white, - child: Row( - children: [ - ClipRRect( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(10), - bottomLeft: Radius.circular(10)), - child: buildCacheNetworkImage( - width: - (MediaQuery.of(context).size.width / 2) * (1.6 / 4) - - 12 - - 1, - height: - (MediaQuery.of(context).size.width / 2) * (1.6 / 4) - - 12 - - 1, - url: homeTrendingData[index].image)), - Expanded( - child: Container( - margin: EdgeInsets.all(10), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, + child: Container( + margin: EdgeInsets.all(8), + child: Column( + children: [ + GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ProductDetailPage( + name: wishlistData.name, + image: wishlistData.image, + price: wishlistData.price, + photo: wishlistData.photo, + rating: wishlistData.rating, + review: wishlistData.review, + sale: wishlistData.sale))); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(homeTrendingData[index].name, - style: TextStyle( - fontSize: 11, fontWeight: FontWeight.bold)), - SizedBox(height: 4), - Text(homeTrendingData[index].sale + ' Product', - style: TextStyle(fontSize: 9, color: BLACK_GREY)) + children: [ + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(10)), + child: buildCacheNetworkImage( + width: boxImageSize, + height: boxImageSize, + url: wishlistData.image)), + SizedBox( + width: 10, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + wishlistData.name, + style: GlobalStyle.productName + .copyWith(fontSize: 13), + maxLines: 3, + overflow: TextOverflow.ellipsis, + ), + Container( + margin: EdgeInsets.only(top: 5), + child: Text( + '\Photo(s) ' + wishlistData.photo.toString(), + style: GlobalStyle.productPrice), + ), + Container( + margin: EdgeInsets.only(top: 5), + child: Row( + children: [ + Icon(Icons.location_on, + color: SOFT_GREY, size: 12), + Text(' ' + wishlistData.location, + style: GlobalStyle.productLocation) + ], + ), + ), + Container( + margin: EdgeInsets.only(top: 5), + child: Row( + children: [ + _reusableWidget.createRatingBar( + rating: wishlistData.rating, size: 12), + Text( + '(' + + wishlistData.review.toString() + + ')', + style: GlobalStyle.productTotalReview) + ], + ), + ), + Container( + margin: EdgeInsets.only(top: 5), + child: Text( + wishlistData.sale.toString() + ' Sale', + style: GlobalStyle.productSale), + ), + ], + ), + ) ], ), ), - ) - ], - )), - ); - } - - Widget _buildLastSearchCard(index, boxImageSize) { - return Container( - width: boxImageSize + 10, - child: Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - elevation: 2, - color: Colors.white, - child: GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ProductDetailPage( - name: lastSearchData[index].name, - image: lastSearchData[index].image, - price: lastSearchData[index].price, - rating: lastSearchData[index].rating, - review: lastSearchData[index].review, - sale: lastSearchData[index].sale))); - }, - child: Column( - children: [ - ClipRRect( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(10), - topRight: Radius.circular(10)), - child: buildCacheNetworkImage( - width: boxImageSize + 10, - height: boxImageSize + 10, - url: lastSearchData[index].image)), - Container( - margin: EdgeInsets.fromLTRB(8, 8, 8, 8), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - lastSearchData[index].name, - style: GlobalStyle.productName, - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - Container( - margin: EdgeInsets.only(top: 5), - child: Text( - '\$ ' + - _globalFunction.removeDecimalZeroFormat( - lastSearchData[index].price), - style: GlobalStyle.productPrice), - ), - Container( - margin: EdgeInsets.only(top: 5), - child: Row( - children: [ - _reusableWidget.createRatingBar( - rating: lastSearchData[index].rating, size: 12), - Text( - '(' + - lastSearchData[index].review.toString() + - ')', - style: GlobalStyle.productTotalReview) - ], + Container( + margin: EdgeInsets.only(top: 12), + child: Row( + children: [ + Expanded( + child: (wishlistData.stock == 0) + ? TextButton( + style: ButtonStyle( + minimumSize: + MaterialStateProperty.all(Size(0, 30)), + backgroundColor: + MaterialStateProperty.resolveWith( + (Set states) => + Colors.grey[300]!, + ), + overlayColor: MaterialStateProperty.all( + Colors.transparent), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0), + )), + ), + onPressed: null, + child: Text( + 'Out of Stock', + style: TextStyle( + color: Colors.grey[600], + fontWeight: FontWeight.bold, + fontSize: 13), + textAlign: TextAlign.center, + )) + : OutlinedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + ProductDetailPage( + name: wishlistData.name, + image: wishlistData.image, + price: wishlistData.price, + photo: wishlistData.photo, + rating: wishlistData.rating, + review: wishlistData.review, + sale: wishlistData.sale))); + }, + style: ButtonStyle( + minimumSize: + MaterialStateProperty.all(Size(0, 30)), + overlayColor: MaterialStateProperty.all( + Colors.transparent), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0), + )), + side: MaterialStateProperty.all( + BorderSide(color: SOFT_BLUE, width: 1.0), + )), + child: Text( + 'Prendre des photos', + style: TextStyle( + color: SOFT_BLUE, + fontWeight: FontWeight.bold, + fontSize: 13), + textAlign: TextAlign.center, + )), ), - ) - ], - ), - ), - ], - ), - ), - ), - ); - } - - Widget _createCategoryForYou( - boxImageSize, categoryForYouHeightShort, categoryForYouHeightLong) { - return Container( - margin: EdgeInsets.only(top: 8), - width: MediaQuery.of(context).size.width, - height: categoryForYouHeightLong, - child: Row( - children: [ - GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ProductCategoryPage( - categoryId: categoryForYouData[0].id, - categoryName: categoryData[0].name))); - }, - child: Container( - width: boxImageSize, - height: categoryForYouHeightLong, - child: buildCacheNetworkImage( - width: 0, height: 0, url: categoryForYouData[0].image), + ], + ), + ) + ], ), ), - Column( - children: [ - Row( - children: [ - GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ProductCategoryPage( - categoryId: categoryForYouData[1].id, - categoryName: categoryData[1].name))); - }, - child: Container( - width: boxImageSize, - height: categoryForYouHeightShort, - child: buildCacheNetworkImage( - width: 0, - height: 0, - url: categoryForYouData[1].image), - ), - ), - GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ProductCategoryPage( - categoryId: categoryForYouData[2].id, - categoryName: categoryData[2].name))); - }, - child: Container( - width: boxImageSize, - height: categoryForYouHeightShort, - child: buildCacheNetworkImage( - width: 0, - height: 0, - url: categoryForYouData[2].image), - ), - ) - ], - ), - Row( - children: [ - GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ProductCategoryPage( - categoryId: categoryForYouData[3].id, - categoryName: categoryData[3].name))); - }, - child: Container( - width: boxImageSize, - height: categoryForYouHeightShort, - child: buildCacheNetworkImage( - width: 0, - height: 0, - url: categoryForYouData[3].image), - ), - ), - GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ProductCategoryPage( - categoryId: categoryForYouData[4].id, - categoryName: categoryData[4].name))); - }, - child: Container( - width: boxImageSize, - height: categoryForYouHeightShort, - child: buildCacheNetworkImage( - width: 0, - height: 0, - url: categoryForYouData[4].image), - ), - ) - ], - ) - ], - ) - ], - ), - ); - } - - Widget _buildRecomendedProductCard(index) { - final double boxImageSize = - ((MediaQuery.of(context).size.width) - 24) / 2 - 12; - return Container( - child: Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - elevation: 2, - color: Colors.white, - child: GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ProductDetailPage( - name: recomendedProductData[index].name, - image: recomendedProductData[index].image, - price: recomendedProductData[index].price, - rating: recomendedProductData[index].rating, - review: recomendedProductData[index].review, - sale: recomendedProductData[index].sale))); - }, - child: Column( - children: [ - ClipRRect( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(10), - topRight: Radius.circular(10)), - child: buildCacheNetworkImage( - width: boxImageSize, - height: boxImageSize, - url: recomendedProductData[index].image)), - Container( - margin: EdgeInsets.fromLTRB(8, 8, 8, 8), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - recomendedProductData[index].name, - style: GlobalStyle.productName, - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - Container( - margin: EdgeInsets.only(top: 5), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - '\$ ' + - _globalFunction.removeDecimalZeroFormat( - recomendedProductData[index].price), - style: GlobalStyle.productPrice), - Text( - recomendedProductData[index].sale.toString() + - ' Sale', - style: TextStyle(fontSize: 11, color: SOFT_GREY)) - ], - ), - ), - Container( - margin: EdgeInsets.only(top: 5), - child: Row( - children: [ - Icon(Icons.location_on, color: SOFT_GREY, size: 12), - Text(' ' + recomendedProductData[index].location, - style: GlobalStyle.productSale) - ], - ), - ), - Container( - margin: EdgeInsets.only(top: 5), - child: Row( - children: [ - _reusableWidget.createRatingBar( - rating: recomendedProductData[index].rating, - size: 12), - Text( - '(' + - recomendedProductData[index] - .review - .toString() + - ')', - style: GlobalStyle.productTotalReview) - ], - ), - ) - ], - ), - ), - ], - ), ), ), ); diff --git a/macos/Podfile.lock b/macos/Podfile.lock new file mode 100644 index 0000000..16959fc --- /dev/null +++ b/macos/Podfile.lock @@ -0,0 +1,44 @@ +PODS: + - FlutterMacOS (1.0.0) + - FMDB (2.7.5): + - FMDB/standard (= 2.7.5) + - FMDB/standard (2.7.5) + - package_info_plus (0.0.1): + - FlutterMacOS + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - sqflite (0.0.2): + - FlutterMacOS + - FMDB (>= 2.7.5) + +DEPENDENCIES: + - FlutterMacOS (from `Flutter/ephemeral`) + - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) + - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos`) + - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) + +SPEC REPOS: + trunk: + - FMDB + +EXTERNAL SOURCES: + FlutterMacOS: + :path: Flutter/ephemeral + package_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos + path_provider_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos + sqflite: + :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos + +SPEC CHECKSUMS: + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce + path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9 + sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea + +PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 + +COCOAPODS: 1.11.3 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index afe113c..0324376 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 460D48F4120F6A092FBB8C86 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49B016110A69499EADAA5A41 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -52,9 +53,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1DBA8B4418C28009A2604251 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* mobdr.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "mobdr.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* mobdr.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = mobdr.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -66,6 +68,9 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 49B016110A69499EADAA5A41 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 624F5C0614E44326DC9ABFA2 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 6B0F9B49233C66D9CA23712E /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ @@ -75,12 +80,24 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 460D48F4120F6A092FBB8C86 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 02999232413A4620F94D542F /* Pods */ = { + isa = PBXGroup; + children = ( + 6B0F9B49233C66D9CA23712E /* Pods-Runner.debug.xcconfig */, + 1DBA8B4418C28009A2604251 /* Pods-Runner.release.xcconfig */, + 624F5C0614E44326DC9ABFA2 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 33BA886A226E78AF003329D5 /* Configs */ = { isa = PBXGroup; children = ( @@ -99,6 +116,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + 02999232413A4620F94D542F /* Pods */, ); sourceTree = ""; }; @@ -148,6 +166,7 @@ D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + 49B016110A69499EADAA5A41 /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -159,11 +178,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + F86FCF2D201694F3D0280F28 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 263F3D5435F1A33D2FF5C6C5 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -233,6 +254,23 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 263F3D5435F1A33D2FF5C6C5 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -271,6 +309,28 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + F86FCF2D201694F3D0280F28 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + +