mirror of
https://github.com/Iconica-Development/flutter_shopping.git
synced 2025-05-19 08:53:46 +02:00
feat: add interface to shopping cart
This commit is contained in:
parent
fd8afbde03
commit
1b78b2c674
9 changed files with 159 additions and 285 deletions
|
@ -2,6 +2,5 @@
|
|||
library flutter_shopping_cart;
|
||||
|
||||
export "src/config/shopping_cart_config.dart";
|
||||
export "src/config/shopping_cart_localizations.dart";
|
||||
export "src/services/product_service.dart";
|
||||
export "src/config/shopping_cart_translations.dart";
|
||||
export "src/widgets/shopping_cart_screen.dart";
|
||||
|
|
|
@ -1,73 +1,48 @@
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter_shopping/flutter_shopping.dart";
|
||||
import "package:flutter_shopping_cart/flutter_shopping_cart.dart";
|
||||
import "package:flutter_shopping_cart/src/widgets/product_item_popup.dart";
|
||||
|
||||
Widget _defaultNoContentBuilder(BuildContext context) =>
|
||||
const SizedBox.shrink();
|
||||
import "package:flutter_shopping_interface/flutter_shopping_interface.dart";
|
||||
|
||||
/// Shopping cart configuration
|
||||
///
|
||||
/// This class is used to configure the shopping cart.
|
||||
class ShoppingCartConfig<T extends Product> {
|
||||
class ShoppingCartConfig {
|
||||
/// Creates a shopping cart configuration.
|
||||
ShoppingCartConfig({
|
||||
required this.productService,
|
||||
required this.service,
|
||||
required this.onConfirmOrder,
|
||||
this.productItemBuilder = _defaultProductItemBuilder,
|
||||
this.onConfirmOrder,
|
||||
this.confirmOrderButtonBuilder,
|
||||
this.confirmOrderButtonBuilder = _defaultConfirmOrderButton,
|
||||
this.confirmOrderButtonHeight = 100,
|
||||
this.sumBottomSheetBuilder,
|
||||
this.sumBottomSheetBuilder = _defaultSumBottomSheetBuilder,
|
||||
this.sumBottomSheetHeight = 100,
|
||||
this.titleBuilder,
|
||||
this.localizations = const ShoppingCartLocalizations(),
|
||||
this.padding = const EdgeInsets.symmetric(horizontal: 32),
|
||||
this.translations = const ShoppingCartTranslations(),
|
||||
this.pagePadding = const EdgeInsets.symmetric(horizontal: 32),
|
||||
this.bottomPadding = const EdgeInsets.fromLTRB(44, 0, 44, 32),
|
||||
this.appBar,
|
||||
Widget Function(BuildContext context) noContentBuilder =
|
||||
_defaultNoContentBuilder,
|
||||
}) : assert(
|
||||
confirmOrderButtonBuilder != null || onConfirmOrder != null,
|
||||
"""
|
||||
If you override the confirm order button builder,
|
||||
you cannot use the onConfirmOrder callback.""",
|
||||
),
|
||||
assert(
|
||||
confirmOrderButtonBuilder == null || onConfirmOrder == null,
|
||||
"""
|
||||
If you do not override the confirm order button builder,
|
||||
you must use the onConfirmOrder callback.""",
|
||||
),
|
||||
_noContentBuilder = noContentBuilder;
|
||||
this.appBar = _defaultAppBar,
|
||||
});
|
||||
|
||||
/// Product Service. The service contains all the products that
|
||||
/// a shopping cart can contain. Each product must extend the [Product] class.
|
||||
/// The service is used to add, remove, and update products.
|
||||
///
|
||||
/// The service can be seperate for each shopping cart in-case you want to
|
||||
/// support seperate shopping carts for shop.
|
||||
ProductService<T> productService = ProductService<T>(<T>[]);
|
||||
/// Product service. The product service is used to manage the products in the
|
||||
/// shopping cart.
|
||||
final ShoppingCartService service;
|
||||
|
||||
/// Product item builder. This builder is used to build the product item
|
||||
/// that will be displayed in the shopping cart.
|
||||
final Widget Function(
|
||||
BuildContext context,
|
||||
Locale locale,
|
||||
Product product,
|
||||
ProductService<Product> productService,
|
||||
ShoppingCartConfig configuration,
|
||||
) productItemBuilder;
|
||||
|
||||
final Widget Function(BuildContext context) _noContentBuilder;
|
||||
|
||||
/// No content builder. This builder is used to build the no content widget
|
||||
/// that will be displayed in the shopping cart when there are no products.
|
||||
Widget Function(BuildContext context) get noContentBuilder =>
|
||||
_noContentBuilder;
|
||||
|
||||
/// Confirm order button builder. This builder is used to build the confirm
|
||||
/// order button that will be displayed in the shopping cart.
|
||||
/// If you override this builder, you cannot use the [onConfirmOrder] callback
|
||||
final Widget Function(BuildContext context)? confirmOrderButtonBuilder;
|
||||
final Widget Function(
|
||||
BuildContext context,
|
||||
ShoppingCartConfig configuration,
|
||||
Function(List<Product> products) onConfirmOrder,
|
||||
) confirmOrderButtonBuilder;
|
||||
|
||||
/// Confirm order button height. The height of the confirm order button.
|
||||
/// This height is used to calculate the bottom padding of the shopping cart.
|
||||
|
@ -78,12 +53,13 @@ you must use the onConfirmOrder callback.""",
|
|||
/// Confirm order callback. This callback is called when the confirm order
|
||||
/// button is pressed. The callback will not be called if you override the
|
||||
/// confirm order button builder.
|
||||
final Function(List<T> products)? onConfirmOrder;
|
||||
final Function(List<Product> products) onConfirmOrder;
|
||||
|
||||
/// Sum bottom sheet builder. This builder is used to build the sum bottom
|
||||
/// sheet that will be displayed in the shopping cart. The sum bottom sheet
|
||||
/// can be used to display the total sum of the products in the shopping cart.
|
||||
final Widget Function(BuildContext context)? sumBottomSheetBuilder;
|
||||
final Widget Function(BuildContext context, ShoppingCartConfig configuration)
|
||||
sumBottomSheetBuilder;
|
||||
|
||||
/// Sum bottom sheet height. The height of the sum bottom sheet.
|
||||
/// This height is used to calculate the bottom padding of the shopping cart.
|
||||
|
@ -92,31 +68,30 @@ you must use the onConfirmOrder callback.""",
|
|||
|
||||
/// Padding around the shopping cart. The padding is used to create space
|
||||
/// around the shopping cart.
|
||||
final EdgeInsets padding;
|
||||
final EdgeInsets pagePadding;
|
||||
|
||||
/// Bottom padding of the shopping cart. The bottom padding is used to create
|
||||
/// a padding around the bottom sheet. This padding is ignored when the
|
||||
/// [sumBottomSheetBuilder] is overridden.
|
||||
final EdgeInsets bottomPadding;
|
||||
|
||||
/// Title builder. This builder is used to build the title of the shopping
|
||||
/// cart. The title is displayed at the top of the shopping cart. If you
|
||||
/// use the title builder, the [title] will be ignored.
|
||||
final Widget Function(BuildContext context)? titleBuilder;
|
||||
/// Title builder. This builder is used to
|
||||
/// build the title of the shopping cart.
|
||||
final Widget Function(
|
||||
BuildContext context,
|
||||
String title,
|
||||
)? titleBuilder;
|
||||
|
||||
/// Shopping cart localizations. The localizations are used to localize the
|
||||
/// shopping cart.
|
||||
final ShoppingCartLocalizations localizations;
|
||||
/// Shopping cart translations. The translations for the shopping cart.
|
||||
final ShoppingCartTranslations translations;
|
||||
|
||||
/// App bar for the shopping cart screen.
|
||||
final PreferredSizeWidget? appBar;
|
||||
/// Appbar for the shopping cart screen.
|
||||
final AppBar Function(BuildContext context) appBar;
|
||||
}
|
||||
|
||||
Widget _defaultProductItemBuilder(
|
||||
BuildContext context,
|
||||
Locale locale,
|
||||
Product product,
|
||||
ProductService<Product> service,
|
||||
ShoppingCartConfig configuration,
|
||||
) {
|
||||
var theme = Theme.of(context);
|
||||
|
@ -172,7 +147,8 @@ Widget _defaultProductItemBuilder(
|
|||
Icons.remove,
|
||||
color: Colors.black,
|
||||
),
|
||||
onPressed: () => service.removeOneProduct(product),
|
||||
onPressed: () =>
|
||||
configuration.service.removeOneProduct(product),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(2),
|
||||
|
@ -198,7 +174,7 @@ Widget _defaultProductItemBuilder(
|
|||
Icons.add,
|
||||
color: Colors.black,
|
||||
),
|
||||
onPressed: () => service.addProduct(product),
|
||||
onPressed: () => configuration.service.addProduct(product),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -207,3 +183,76 @@ Widget _defaultProductItemBuilder(
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _defaultSumBottomSheetBuilder(
|
||||
BuildContext context,
|
||||
ShoppingCartConfig configuration,
|
||||
) {
|
||||
var theme = Theme.of(context);
|
||||
|
||||
var totalPrice = configuration.service.products
|
||||
.map((product) => product.price * product.quantity)
|
||||
.fold(0.0, (a, b) => a + b);
|
||||
|
||||
return Padding(
|
||||
padding: configuration.bottomPadding,
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
configuration.translations.sum,
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
"€ ${totalPrice.toStringAsFixed(2)}",
|
||||
style: theme.textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _defaultConfirmOrderButton(
|
||||
BuildContext context,
|
||||
ShoppingCartConfig configuration,
|
||||
Function(List<Product> products) onConfirmOrder,
|
||||
) {
|
||||
var theme = Theme.of(context);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 60),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: FilledButton(
|
||||
onPressed: () => onConfirmOrder(
|
||||
configuration.service.products,
|
||||
),
|
||||
style: theme.filledButtonTheme.style?.copyWith(
|
||||
backgroundColor: WidgetStateProperty.all(
|
||||
theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 12,
|
||||
),
|
||||
child: Text(
|
||||
configuration.translations.placeOrder,
|
||||
style: theme.textTheme.displayLarge,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
AppBar _defaultAppBar(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
return AppBar(
|
||||
title: Text(
|
||||
"Shopping cart",
|
||||
style: theme.textTheme.headlineLarge,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,24 +1,14 @@
|
|||
import "package:flutter/material.dart";
|
||||
|
||||
/// Shopping cart localizations
|
||||
class ShoppingCartLocalizations {
|
||||
class ShoppingCartTranslations {
|
||||
/// Creates shopping cart localizations
|
||||
const ShoppingCartLocalizations({
|
||||
this.locale = const Locale("en", "US"),
|
||||
const ShoppingCartTranslations({
|
||||
this.placeOrder = "Order",
|
||||
this.sum = "Subtotal:",
|
||||
this.cartTitle = "Products",
|
||||
this.close = "close",
|
||||
});
|
||||
|
||||
/// Locale for the shopping cart.
|
||||
/// This locale will be used to format the currency.
|
||||
/// Default is English.
|
||||
final Locale locale;
|
||||
|
||||
/// Localization for the place order button.
|
||||
/// This text will only be displayed if you're not using the place order
|
||||
/// button builder.
|
||||
/// Text for the place order button.
|
||||
final String placeOrder;
|
||||
|
||||
/// Localization for the sum.
|
|
@ -1,71 +0,0 @@
|
|||
import "package:flutter/foundation.dart";
|
||||
import "package:flutter_shopping/flutter_shopping.dart";
|
||||
|
||||
/// Product service. This class is responsible for managing the products.
|
||||
/// The service is used to add, remove, and update products.
|
||||
class ProductService<T extends Product> extends ChangeNotifier {
|
||||
/// Creates a product service.
|
||||
ProductService(this.products);
|
||||
|
||||
/// List of products in the shopping cart.
|
||||
final List<T> products;
|
||||
|
||||
/// Adds a product to the shopping cart.
|
||||
void addProduct(T product) {
|
||||
for (var p in products) {
|
||||
if (p.id == product.id) {
|
||||
p.quantity++;
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
products.add(product);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Removes a product from the shopping cart.
|
||||
void removeProduct(T product) {
|
||||
for (var p in products) {
|
||||
if (p.id == product.id) {
|
||||
products.remove(p);
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Removes one product from the shopping cart.
|
||||
void removeOneProduct(T product) {
|
||||
for (var p in products) {
|
||||
if (p.id == product.id) {
|
||||
if (p.quantity > 1) {
|
||||
p.quantity--;
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
products.remove(product);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Counts the number of products in the shopping cart.
|
||||
int countProducts() {
|
||||
var count = 0;
|
||||
|
||||
for (var product in products) {
|
||||
count += product.quantity;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/// Empties the shopping cart.
|
||||
void clear() {
|
||||
products.clear();
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter_shopping/flutter_shopping.dart";
|
||||
import "package:flutter_shopping_cart/flutter_shopping_cart.dart";
|
||||
import "package:flutter_shopping_interface/flutter_shopping_interface.dart";
|
||||
|
||||
/// A popup that displays the product item.
|
||||
class ProductItemPopup extends StatelessWidget {
|
||||
|
@ -49,7 +50,7 @@ class ProductItemPopup extends StatelessWidget {
|
|||
vertical: 8.0,
|
||||
),
|
||||
child: Text(
|
||||
configuration.localizations.close,
|
||||
configuration.translations.close,
|
||||
style: theme.textTheme.displayLarge,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter_shopping/flutter_shopping.dart";
|
||||
import "package:flutter_shopping_cart/flutter_shopping_cart.dart";
|
||||
|
||||
/// Shopping cart screen widget.
|
||||
class ShoppingCartScreen<T extends Product> extends StatelessWidget {
|
||||
class ShoppingCartScreen extends StatelessWidget {
|
||||
/// Creates a shopping cart screen.
|
||||
const ShoppingCartScreen({
|
||||
required this.configuration,
|
||||
|
@ -10,7 +10,7 @@ class ShoppingCartScreen<T extends Product> extends StatelessWidget {
|
|||
});
|
||||
|
||||
/// Configuration for the shopping cart screen.
|
||||
final ShoppingCartConfig<T> configuration;
|
||||
final ShoppingCartConfig configuration;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -20,7 +20,10 @@ class ShoppingCartScreen<T extends Product> extends StatelessWidget {
|
|||
child: Column(
|
||||
children: [
|
||||
if (configuration.titleBuilder != null) ...{
|
||||
configuration.titleBuilder!(context),
|
||||
configuration.titleBuilder!(
|
||||
context,
|
||||
configuration.translations.cartTitle,
|
||||
),
|
||||
} else ...{
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
|
@ -29,7 +32,7 @@ class ShoppingCartScreen<T extends Product> extends StatelessWidget {
|
|||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
configuration.localizations.cartTitle,
|
||||
configuration.translations.cartTitle,
|
||||
style: theme.textTheme.titleLarge,
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
|
@ -38,22 +41,16 @@ class ShoppingCartScreen<T extends Product> extends StatelessWidget {
|
|||
),
|
||||
},
|
||||
ListenableBuilder(
|
||||
listenable: configuration.productService,
|
||||
listenable: configuration.service,
|
||||
builder: (context, _) {
|
||||
var products = configuration.productService.products;
|
||||
|
||||
if (products.isEmpty) {
|
||||
return configuration.noContentBuilder(context);
|
||||
}
|
||||
var products = configuration.service.products;
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
for (var product in products)
|
||||
configuration.productItemBuilder(
|
||||
context,
|
||||
configuration.localizations.locale,
|
||||
product,
|
||||
configuration.productService,
|
||||
configuration,
|
||||
),
|
||||
// Additional whitespace at the bottom to make sure the
|
||||
|
@ -71,24 +68,18 @@ class ShoppingCartScreen<T extends Product> extends StatelessWidget {
|
|||
);
|
||||
|
||||
return Scaffold(
|
||||
appBar: configuration.appBar ??
|
||||
AppBar(
|
||||
title: Text(
|
||||
"Shopping cart",
|
||||
style: theme.textTheme.headlineLarge,
|
||||
),
|
||||
),
|
||||
appBar: configuration.appBar.call(context),
|
||||
body: SafeArea(
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Padding(
|
||||
padding: configuration.padding,
|
||||
padding: configuration.pagePadding,
|
||||
child: productBuilder,
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: _BottomSheet<T>(
|
||||
child: _BottomSheet(
|
||||
configuration: configuration,
|
||||
),
|
||||
),
|
||||
|
@ -99,124 +90,31 @@ class ShoppingCartScreen<T extends Product> extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
class _BottomSheet<T extends Product> extends StatelessWidget {
|
||||
class _BottomSheet extends StatelessWidget {
|
||||
const _BottomSheet({
|
||||
required this.configuration,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final ShoppingCartConfig<T> configuration;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var placeOrderButton = ListenableBuilder(
|
||||
listenable: configuration.productService,
|
||||
builder: (BuildContext context, Widget? child) =>
|
||||
configuration.confirmOrderButtonBuilder != null
|
||||
? configuration.confirmOrderButtonBuilder!(context)
|
||||
: _DefaultConfirmOrderButton<T>(configuration: configuration),
|
||||
);
|
||||
|
||||
var bottomSheet = ListenableBuilder(
|
||||
listenable: configuration.productService,
|
||||
builder: (BuildContext context, Widget? child) =>
|
||||
configuration.sumBottomSheetBuilder != null
|
||||
? configuration.sumBottomSheetBuilder!(context)
|
||||
: _DefaultSumBottomSheet(configuration: configuration),
|
||||
);
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
bottomSheet,
|
||||
placeOrderButton,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DefaultConfirmOrderButton<T extends Product> extends StatelessWidget {
|
||||
const _DefaultConfirmOrderButton({
|
||||
required this.configuration,
|
||||
});
|
||||
|
||||
final ShoppingCartConfig<T> configuration;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
|
||||
void onConfirmOrderPressed(List<T> products) {
|
||||
if (configuration.onConfirmOrder == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (products.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
configuration.onConfirmOrder!(products);
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 60),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: FilledButton(
|
||||
onPressed: () => onConfirmOrderPressed(
|
||||
configuration.productService.products,
|
||||
),
|
||||
style: theme.filledButtonTheme.style?.copyWith(
|
||||
backgroundColor: WidgetStateProperty.all(
|
||||
theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 12,
|
||||
),
|
||||
child: Text(
|
||||
configuration.localizations.placeOrder,
|
||||
style: theme.textTheme.displayLarge,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DefaultSumBottomSheet extends StatelessWidget {
|
||||
const _DefaultSumBottomSheet({
|
||||
required this.configuration,
|
||||
});
|
||||
|
||||
final ShoppingCartConfig configuration;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
|
||||
var totalPrice = configuration.productService.products
|
||||
.map((product) => product.price * product.quantity)
|
||||
.fold(0.0, (a, b) => a + b);
|
||||
|
||||
return Padding(
|
||||
padding: configuration.bottomPadding,
|
||||
child: Row(
|
||||
Widget build(BuildContext context) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
configuration.localizations.sum,
|
||||
style: theme.textTheme.titleMedium,
|
||||
ListenableBuilder(
|
||||
listenable: configuration.service,
|
||||
builder: (BuildContext context, Widget? child) =>
|
||||
configuration.sumBottomSheetBuilder(context, configuration),
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
"€ ${totalPrice.toStringAsFixed(2)}",
|
||||
style: theme.textTheme.bodyMedium,
|
||||
ListenableBuilder(
|
||||
listenable: configuration.service,
|
||||
builder: (BuildContext context, Widget? child) =>
|
||||
configuration.confirmOrderButtonBuilder(
|
||||
context,
|
||||
configuration,
|
||||
configuration.onConfirmOrder,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
name: flutter_shopping_cart
|
||||
description: "A Flutter module for a shopping cart."
|
||||
version: 2.0.0
|
||||
publish_to: 'none'
|
||||
publish_to: "none"
|
||||
|
||||
environment:
|
||||
sdk: '>=3.3.0 <4.0.0'
|
||||
sdk: ">=3.3.0 <4.0.0"
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_shopping:
|
||||
flutter_shopping_interface:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_shopping
|
||||
path: packages/flutter_shopping
|
||||
path: packages/flutter_shopping_interface
|
||||
ref: 2.0.0
|
||||
|
||||
dependency_overrides:
|
||||
flutter_shopping_interface:
|
||||
path: ../flutter_shopping_interface
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
@ -17,4 +17,7 @@ abstract class ShoppingCartService with ChangeNotifier {
|
|||
|
||||
/// Clears the shopping cart.
|
||||
void clear();
|
||||
|
||||
/// The list of products in the shopping cart.
|
||||
List<Product> get products;
|
||||
}
|
||||
|
|
|
@ -54,4 +54,7 @@ class LocalShoppingCartService
|
|||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
List<Product> get products => _products;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue