diff --git a/lib/pages/basket.dart b/lib/pages/basket.dart index 668de09..9936d14 100644 --- a/lib/pages/basket.dart +++ b/lib/pages/basket.dart @@ -4,6 +4,8 @@ import 'package:gymlink_module_web/components/basket_item_card.dart'; import 'package:gymlink_module_web/components/heading.dart'; import 'package:gymlink_module_web/pages/order_confirmation.dart'; import 'package:gymlink_module_web/tools/prefs.dart'; +import 'package:gymlink_module_web/tools/routes.dart'; +import 'package:lazy_load_scrollview/lazy_load_scrollview.dart'; List> cart = [ { @@ -195,6 +197,12 @@ class _BasketPageState extends State { return const SizedBox(height: 10); } + void _onLoad() async { + await Future.delayed(const Duration(microseconds: 1000)); + + setState(() {}); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -212,7 +220,7 @@ class _BasketPageState extends State { style: Theme.of(context).textTheme.bodyLarge), const SizedBox(height: 10), ElevatedButton( - onPressed: () => Navigator.pop(context), + onPressed: () => Navigator.pop(context, true), style: ElevatedButton.styleFrom( backgroundColor: Theme.of(context).primaryColor, shape: const RoundedRectangleBorder( @@ -232,24 +240,28 @@ class _BasketPageState extends State { context: context, children: [ Expanded( - child: ListView.builder( - itemCount: cartItems.length, - itemBuilder: (context, index) { - final item = cartItems[index]; - return BasketItemCard( - name: item['name'], - price: item['price'], - id: item['id'], - image: Image( - image: AssetImage('assets/${item['image']}'), - width: 50, - ), - onTapPlus: () => addItem(item['id'].toString()), - onTapMinus: () => - removeItem(item['id'].toString()), - quantity: item['count'].toString(), - ); - }, + child: LazyLoadScrollView( + onEndOfPage: _onLoad, + child: ListView.builder( + itemCount: cartItems.length, + itemBuilder: (context, index) { + final item = cartItems[index]; + return BasketItemCard( + name: item['name'], + price: item['price'], + id: item['id'], + image: Image( + image: AssetImage('assets/${item['image']}'), + width: 50, + ), + onTapPlus: () => addItem(item['id'].toString()), + onTapMinus: () { + removeItem(item['id'].toString()); + }, + quantity: item['count'].toString(), + ); + }, + ), ), ), _buildSpacer(), @@ -263,7 +275,7 @@ class _BasketPageState extends State { ), ElevatedButton( onPressed: () => Navigator.of(context).push( - MaterialPageRoute( + CustomPageRoute( builder: (context) => const OrderConfirmationPage(), ), diff --git a/lib/pages/main.dart b/lib/pages/main.dart index a0260a0..fdc37ac 100644 --- a/lib/pages/main.dart +++ b/lib/pages/main.dart @@ -1,15 +1,20 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; import 'package:gymlink_module_web/components/app_bar.dart'; import 'package:gymlink_module_web/components/item_card.dart'; import 'package:gymlink_module_web/pages/basket.dart'; import 'package:gymlink_module_web/pages/detail.dart'; import 'package:gymlink_module_web/pages/order_history.dart'; +import 'package:gymlink_module_web/tools/prefs.dart'; import 'package:gymlink_module_web/tools/relative.dart'; +import 'package:gymlink_module_web/tools/routes.dart'; +import 'package:lazy_load_scrollview/lazy_load_scrollview.dart'; import 'package:url_launcher/url_launcher.dart'; const List> testData = [ { - "name": "Протеин", + "name": "Протеин 2", "image": "product.png", "price": "120", "details": "Test details", @@ -59,6 +64,25 @@ class MainPage extends StatefulWidget { } class _MainPageState extends State { + String searchText = ''; + List> filteredData = []; + int cartLength = 0; + + @override + void initState() { + super.initState(); + filteredData = testData; + getCart().then((value) { + setState(() { + cartLength = value.length; + }); + }).whenComplete(() { + if (mounted) { + setState(() {}); + } + }); + } + Future _goToPage() async { final Uri url = Uri.parse('https://google.com'); if (!await launchUrl(url, webOnlyWindowName: '_blank')) { @@ -66,6 +90,19 @@ class _MainPageState extends State { } } + void _onLoad() async { + await Future.delayed(const Duration(milliseconds: 1000)); + debugPrint('aye'); + } + + void _onSearch() { + setState(() { + filteredData = testData + .where((element) => (element['name']!).contains(searchText)) + .toList(); + }); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -82,15 +119,18 @@ class _MainPageState extends State { children: [ Expanded( child: TextField( + onChanged: (value) => setState(() { + searchText = value; + }), decoration: InputDecoration( - hintText: 'Search', + hintText: 'Поиск', border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), ), suffixIcon: Padding( padding: const EdgeInsets.only(right: 8), child: ElevatedButton( - onPressed: _goToPage, + onPressed: _onSearch, style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric( vertical: 8, @@ -113,35 +153,12 @@ class _MainPageState extends State { ), ), getSpacer(context: context, flex: 2), - ElevatedButton( - onPressed: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (context) => const BasketPage(), - )); - }, - style: ElevatedButton.styleFrom( - padding: const EdgeInsets.all(0), - minimumSize: const Size(50, kMinInteractiveDimension), - backgroundColor: Theme.of(context).primaryColor, - shape: const CircleBorder( - side: BorderSide( - color: Colors.black, - width: 1, - ), - ), - ), - child: const Icon( - Icons.shopping_basket, - color: Colors.white, - size: 24, - ), - ), const SizedBox( width: 8, ), ElevatedButton( onPressed: () { - Navigator.of(context).push(MaterialPageRoute( + Navigator.of(context).push(CustomPageRoute( builder: (context) => const HistoryPage(), )); }, @@ -169,41 +186,94 @@ class _MainPageState extends State { ), ), Expanded( - child: GridView.builder( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: (MediaQuery.sizeOf(context).width ~/ 150) - .floor(), //TODO: Make it adaptive size - ), - itemCount: testData.length, - itemBuilder: (context, index) { - final product = testData[index]; - return ProductCard( - imagePath: Image( - image: AssetImage('assets/${product['image']!}'), - width: 50, - ), - name: product['name']!, - price: product['price']!, - onTap: () => Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => DetailPage( - name: product['name']!, - description: product['details']!, - price: product['price']!, - id: product['id']!, - image: Image( - image: - AssetImage('assets/${product['image']!}'), - width: 300), - ), + child: LazyLoadScrollView( + onEndOfPage: _onLoad, + child: Stack( + children: [ + GridView.builder( + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: min( + (MediaQuery.sizeOf(context).width ~/ 200) + .toInt(), + 8), ), + itemCount: filteredData.length, + itemBuilder: (context, index) { + final product = filteredData[index]; + return ProductCard( + imagePath: Image( + image: Image.network( + 'https://rus-sport.net/upload/iblock/311/topb85ez18pq0aavohpa5zipk2sbfxll.jpg') + .image, + width: 50, + ), + name: product['name']!, + price: product['price']!, + onTap: () => Navigator.of(context).push( + CustomPageRoute( + builder: (context) => DetailPage( + name: product['name']!, + description: product['details']!, + price: product['price']!, + id: product['id']!, + image: Image( + image: AssetImage( + 'assets/${product['image']!}'), + width: 300), + ), + ), + ), + ); + }, ), - ); - }, + ], + ), ), ), ], ), + floatingActionButton: SizedBox( + height: 80, + width: 80, + child: FittedBox( + child: Stack( + children: [ + FloatingActionButton( + onPressed: () => Navigator.of(context).push(CustomPageRoute( + builder: (context) => const BasketPage(), + )), + backgroundColor: Colors.transparent, + elevation: 0, + child: CircleAvatar( + radius: 25, + backgroundColor: Theme.of(context).primaryColor, + foregroundColor: Colors.white, + child: const Icon(Icons.shopping_cart_outlined)), + ), + cartLength > 0 + ? Positioned( + right: -3, + bottom: 0, + child: Card( + color: Colors.red, + child: SizedBox( + width: 20, + child: Center( + child: Text( + cartLength.toString(), + style: const TextStyle(color: Colors.white), + ), + ), + ), + ), + ) + : const SizedBox.shrink(), + ], + ), + ), + ), + floatingActionButtonLocation: FloatingActionButtonLocation.startFloat, ); } } diff --git a/lib/pages/order_confirmation.dart b/lib/pages/order_confirmation.dart index 96d3421..3ef9019 100644 --- a/lib/pages/order_confirmation.dart +++ b/lib/pages/order_confirmation.dart @@ -75,6 +75,7 @@ class _OrderConfirmationPageState extends State { Widget build(BuildContext context) { return Scaffold( appBar: const GymLinkAppBar(), + resizeToAvoidBottomInset: false, body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -117,6 +118,17 @@ class _OrderConfirmationPageState extends State { ), ), ), + Expanded( + child: TextField( + decoration: InputDecoration( + hintText: 'Электронная почта', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + keyboardType: TextInputType.emailAddress, + ), + ), Expanded( child: TextField( decoration: InputDecoration( @@ -129,7 +141,7 @@ class _OrderConfirmationPageState extends State { ), ElevatedButton( onPressed: () { - print('debugprint'); + debugPrint('debugprint'); // if (kIsWeb) { // Navigator.of(context).push( // MaterialPageRoute( diff --git a/lib/pages/order_history.dart b/lib/pages/order_history.dart index 443391b..cef463f 100644 --- a/lib/pages/order_history.dart +++ b/lib/pages/order_history.dart @@ -3,6 +3,7 @@ import 'package:gymlink_module_web/components/app_bar.dart'; import 'package:gymlink_module_web/components/heading.dart'; import 'package:gymlink_module_web/components/history_item_card.dart'; import 'package:gymlink_module_web/tools/relative.dart'; +import 'package:lazy_load_scrollview/lazy_load_scrollview.dart'; List> orders = [ {"image": "product.png", "price": "120", "id": "66", "date": "11.09.2001"}, @@ -32,11 +33,42 @@ List> orders = [ } ]; -class HistoryPage extends StatelessWidget { +class HistoryPage extends StatefulWidget { const HistoryPage({ super.key, }); + @override + State createState() => _HistoryPageState(); +} + +class _HistoryPageState extends State { + List> my_orders = []; + + @override + void initState() { + super.initState(); + my_orders = orders; + } + + void _onLoad() async { + await Future.delayed(const Duration(milliseconds: 1000)); + setState(() { + my_orders.add( + { + "image": "product.png", + "price": "120", + "id": "666666", + "date": "11.09.2001" + }, + ); + }); + } + + Future _onRefresh() async { + await Future.delayed(const Duration(milliseconds: 1000)); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -49,21 +81,33 @@ class HistoryPage extends StatelessWidget { child: Row( children: [ Expanded( - child: ListView.builder( - itemCount: orders.length, - itemBuilder: (context, index) { - final item = orders[index]; - return HistoryItemCard( - id: item['id']!, - cost: item['price']!, - date: item['date']!, - image: Image( - image: AssetImage('assets/${item['image']!}'), - width: 50, - ), - status: OrderStatus.completed, - ); - }, + child: LazyLoadScrollView( + onEndOfPage: _onLoad, + scrollOffset: 200, + child: RefreshIndicator( + edgeOffset: 55, + onRefresh: _onRefresh, + child: Stack( + children: [ + ListView.builder( + itemCount: my_orders.length, + itemBuilder: (context, index) { + final item = my_orders[index]; + return HistoryItemCard( + id: item['id']!, + cost: item['price']!, + date: item['date']!, + image: Image( + image: AssetImage('assets/${item['image']!}'), + width: 50, + ), + status: OrderStatus.completed, + ); + }, + ), + ], + ), + ), ), ), getSpacer(context: context) diff --git a/lib/tools/routes.dart b/lib/tools/routes.dart new file mode 100644 index 0000000..4c32312 --- /dev/null +++ b/lib/tools/routes.dart @@ -0,0 +1,8 @@ +import 'package:flutter/material.dart'; + +class CustomPageRoute extends MaterialPageRoute { + CustomPageRoute({builder}) : super(builder: builder); + + @override + Duration get transitionDuration => const Duration(milliseconds: 0); +}