From 0c11883b48d8fa54d93ea1258b9e59923cfc8e42 Mon Sep 17 00:00:00 2001 From: Sergey Elpashev Date: Fri, 10 May 2024 22:08:27 +0300 Subject: [PATCH] Basket confirmation page --- lib/components/basket_item_card.dart | 2 +- lib/components/history_item_card.dart | 2 +- lib/components/order_confirm_item_card.dart | 62 ++++++++ lib/pages/basket.dart | 8 +- lib/pages/order_confirmation.dart | 148 ++++++++++++++++++++ 5 files changed, 219 insertions(+), 3 deletions(-) create mode 100644 lib/components/order_confirm_item_card.dart create mode 100644 lib/pages/order_confirmation.dart diff --git a/lib/components/basket_item_card.dart b/lib/components/basket_item_card.dart index 1a7d91e..ef8a93a 100644 --- a/lib/components/basket_item_card.dart +++ b/lib/components/basket_item_card.dart @@ -34,7 +34,7 @@ class BasketItemCard extends StatelessWidget { ), child: Card( elevation: 4, - color: const Color(0xFFF2F3F9), + color: Theme.of(context).scaffoldBackgroundColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), ), diff --git a/lib/components/history_item_card.dart b/lib/components/history_item_card.dart index 12d1e93..6d3b739 100644 --- a/lib/components/history_item_card.dart +++ b/lib/components/history_item_card.dart @@ -40,7 +40,7 @@ class HistoryItemCard extends StatelessWidget { ), child: Card( elevation: 4, - color: const Color(0xFFF2F3F9), + color: Theme.of(context).scaffoldBackgroundColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), ), diff --git a/lib/components/order_confirm_item_card.dart b/lib/components/order_confirm_item_card.dart new file mode 100644 index 0000000..edffaa7 --- /dev/null +++ b/lib/components/order_confirm_item_card.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_markdown/flutter_markdown.dart'; + +class OrderConfirmItemCard extends StatelessWidget { + final String name; + final int count; + final double price; + final Image image; + + const OrderConfirmItemCard({ + super.key, + required this.name, + required this.count, + required this.price, + required this.image, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: + const EdgeInsetsDirectional.symmetric(horizontal: 10, vertical: 10), + child: ConstrainedBox( + constraints: const BoxConstraints(minHeight: 130), + child: Card( + elevation: 4, + color: Theme.of(context).scaffoldBackgroundColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(30), + ), + child: Padding( + padding: const EdgeInsetsDirectional.symmetric(horizontal: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + image, + const SizedBox(width: 20), + Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + name, + style: Theme.of(context).textTheme.bodyLarge, + ), + Text('\$$price x $count = \$${price * count}'), + ], + ) + ], + ), + MarkdownBody(data: '# X$count') + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/basket.dart b/lib/pages/basket.dart index cd3cd26..6c147ec 100644 --- a/lib/pages/basket.dart +++ b/lib/pages/basket.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:gymlink_module_web/components/app_bar.dart'; 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'; List> cart = [ @@ -245,7 +246,12 @@ class _BasketPageState extends State { 'Итого: $totalPrice', ), ElevatedButton( - onPressed: () {}, + onPressed: () => Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => + const OrderConfirmationPage(), + ), + ), style: ElevatedButton.styleFrom( backgroundColor: Theme.of(context).primaryColor, shape: const RoundedRectangleBorder( diff --git a/lib/pages/order_confirmation.dart b/lib/pages/order_confirmation.dart new file mode 100644 index 0000000..d8c442a --- /dev/null +++ b/lib/pages/order_confirmation.dart @@ -0,0 +1,148 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_markdown/flutter_markdown.dart'; +import 'package:gymlink_module_web/components/app_bar.dart'; +import 'package:gymlink_module_web/components/heading.dart'; +import 'package:gymlink_module_web/components/order_confirm_item_card.dart'; +import 'package:gymlink_module_web/tools/prefs.dart'; + +List> cart = [ + { + "name": "Протеин", + "image": "product.png", + "price": "120", + "details": "Test details", + "id": "34fa3126-bfaf-5dec-8f4a-b246c097ef73" + }, + { + "name": "Протеин", + "image": "product.png", + "price": "150", + "details": "Test details", + "id": "34a26e82-7656-5e98-a44a-c2d01d0b1ad1123" + }, + { + "name": "Протеин", + "image": "product.png", + "price": "250", + "details": "Test details", + "id": "4fb204b7-3f9e-52a2-bed1-415c00a31a37123" + }, + { + "name": "Протеин", + "image": "product.png", + "price": "300", + "details": "Test details", + "id": "09b2f5bb-683e-5c39-ae89-b8e152fa8bcf123" + }, + { + "name": "Протеин", + "image": "product.png", + "price": "100", + "details": "Test details", + "id": "cd1b6817-db94-5394-be1d-af88af79749f123" + } +]; + +class OrderConfirmationPage extends StatefulWidget { + const OrderConfirmationPage({super.key}); + + @override + State createState() => _OrderConfirmationPageState(); +} + +class _OrderConfirmationPageState extends State { + List> cartItems = []; + int totalPrice = 0; + + @override + void initState() { + super.initState(); + getCart().then((value) { + setState(() { + cartItems = value.map((element) { + final item = cart.firstWhere((e) => e['id'] == element['id']); + return {...item, 'count': element['count'] as int}; + }).toList(); + totalPrice = cartItems.fold( + 0, + (sum, item) => + sum + int.parse(item['price']) * item['count'] as int); + }); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: const GymLinkAppBar(), + body: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const GymLinkHeader(title: 'Оформление заказа'), + const MarkdownBody(data: '## Состав заказа:'), + Expanded( + child: ConstrainedBox( + constraints: const BoxConstraints(maxHeight: 350), + child: ListView.builder( + itemCount: cartItems.length, + itemBuilder: (context, index) { + final item = cartItems[index]; + return OrderConfirmItemCard( + name: item['name'], + image: Image.asset(item['image'], width: 50, height: 50), + price: double.parse(item['price']), + count: item['count'], + ); + }, + ), + ), + ), + const SizedBox( + height: 10, + ), + Expanded( + child: Column( + children: [ + MarkdownBody(data: '## Итого: $totalPrice'), + Expanded( + child: TextField( + decoration: InputDecoration( + hintText: 'Адрес доставки', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + ), + ), + Expanded( + child: TextField( + decoration: InputDecoration( + hintText: 'Получатель', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + ), + ), + ElevatedButton( + onPressed: () { + debugPrint('Order confirmed'); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Theme.of(context).primaryColor, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + foregroundColor: Colors.white, + ), + child: const Text('Оформить заказ'), + ), + const SizedBox(height: 20), + ], + ), + ), + ], + ), + ); + } +}