mirror of
https://github.com/Iconica-Development/flutter_shopping.git
synced 2025-05-18 16:33:45 +02:00
feat(example): add amazon product page example
This commit is contained in:
parent
e201120bc2
commit
a38e97c68f
13 changed files with 763 additions and 0 deletions
53
example_amazon/.gitignore
vendored
Normal file
53
example_amazon/.gitignore
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
.metadata
|
||||
pubspec.lock
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
||||
|
||||
# Android Studio will place build artifacts here
|
||||
/android/app/debug
|
||||
/android/app/profile
|
||||
/android/app/release
|
||||
|
||||
# Platforms
|
||||
/android/
|
||||
/ios/
|
||||
/linux/
|
||||
/macos/
|
||||
/web/
|
||||
/windows/
|
16
example_amazon/README.md
Normal file
16
example_amazon/README.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# amazon
|
||||
|
||||
A new Flutter project.
|
||||
|
||||
## Getting Started
|
||||
|
||||
This project is a starting point for a Flutter application.
|
||||
|
||||
A few resources to get you started if this is your first Flutter project:
|
||||
|
||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
||||
|
||||
For help getting started with Flutter development, view the
|
||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
||||
samples, guidance on mobile development, and a full API reference.
|
28
example_amazon/analysis_options.yaml
Normal file
28
example_amazon/analysis_options.yaml
Normal file
|
@ -0,0 +1,28 @@
|
|||
# This file configures the analyzer, which statically analyzes Dart code to
|
||||
# check for errors, warnings, and lints.
|
||||
#
|
||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||
# invoked from the command line by running `flutter analyze`.
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
# The lint rules applied to this project can be customized in the
|
||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||
# included above or to enable additional rules. A list of all available lints
|
||||
# and their documentation is published at https://dart.dev/lints.
|
||||
#
|
||||
# Instead of disabling a lint rule for the entire project in the
|
||||
# section below, it can also be suppressed for a single line of code
|
||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||
# producing the lint.
|
||||
rules:
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
22
example_amazon/lib/main.dart
Normal file
22
example_amazon/lib/main.dart
Normal file
|
@ -0,0 +1,22 @@
|
|||
import "package:amazon/src/routes.dart";
|
||||
import "package:amazon/src/utils/theme.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
|
||||
void main() {
|
||||
runApp(const ProviderScope(child: MyApp()));
|
||||
}
|
||||
|
||||
class MyApp extends HookConsumerWidget {
|
||||
const MyApp({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) => MaterialApp.router(
|
||||
debugShowCheckedModeBanner: false,
|
||||
restorationScopeId: "app",
|
||||
theme: getTheme(),
|
||||
routerConfig: ref.read(routerProvider),
|
||||
);
|
||||
}
|
361
example_amazon/lib/src/configuration/shopping_configuration.dart
Normal file
361
example_amazon/lib/src/configuration/shopping_configuration.dart
Normal file
|
@ -0,0 +1,361 @@
|
|||
import "package:amazon/src/models/my_product.dart";
|
||||
import "package:amazon/src/routes.dart";
|
||||
import "package:amazon/src/services/category_service.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_product_page/flutter_product_page.dart";
|
||||
import "package:flutter_shopping/flutter_shopping.dart";
|
||||
import "package:flutter_shopping_cart/flutter_shopping_cart.dart";
|
||||
import "package:go_router/go_router.dart";
|
||||
|
||||
// (REQUIRED): Create your own instance of the ProductService.
|
||||
final ProductService<MyProduct> productService = ProductService([]);
|
||||
|
||||
FlutterShoppingConfiguration getFlutterShoppingConfiguration() =>
|
||||
FlutterShoppingConfiguration(
|
||||
// (REQUIRED): Shop builder configuration
|
||||
shopBuilder: (
|
||||
BuildContext context,
|
||||
String? initialBuildShopId,
|
||||
String? streetName,
|
||||
) {
|
||||
var theme = Theme.of(context);
|
||||
|
||||
return ProductPageScreen(
|
||||
configuration: ProductPageConfiguration(
|
||||
// (REQUIRED): List of shops that should be displayed
|
||||
// If there is only one, make a list with just one shop.
|
||||
shops: Future.value(getCategories()),
|
||||
|
||||
pagePadding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
|
||||
|
||||
// (REQUIRED): Function to add a product to the cart
|
||||
onAddToCart: (ProductPageProduct product) =>
|
||||
productService.addProduct(product as MyProduct),
|
||||
|
||||
// (REQUIRED): Function to get the products for a shop
|
||||
getProducts: (ProductPageShop shop) =>
|
||||
Future<ProductPageContent>.value(
|
||||
getShopContent(shop.id),
|
||||
),
|
||||
|
||||
// (REQUIRED): Function to navigate to the shopping cart
|
||||
onNavigateToShoppingCart: () => onCompleteProductPage(context),
|
||||
|
||||
shopSelectorStyle: ShopSelectorStyle.row,
|
||||
|
||||
navigateToShoppingCartBuilder: (context) => const SizedBox.shrink(),
|
||||
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
fixedColor: theme.primaryColor,
|
||||
unselectedItemColor: Colors.black,
|
||||
type: BottomNavigationBarType.fixed,
|
||||
items: const [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.home),
|
||||
label: "Home",
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.person_2_outlined),
|
||||
label: "Profile",
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.shopping_cart_outlined),
|
||||
label: "Cart",
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.menu),
|
||||
label: "Menu",
|
||||
),
|
||||
],
|
||||
showSelectedLabels: false,
|
||||
showUnselectedLabels: false,
|
||||
onTap: (index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
// context.go(homePage);
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
context.go(FlutterShoppingPathRoutes.shoppingCart);
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
productBuilder: (context, product) => Card(
|
||||
elevation: 0,
|
||||
color: const Color.fromARGB(255, 233, 233, 233),
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.zero,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Image.network(
|
||||
product.imageUrl,
|
||||
loadingBuilder: (context, child, loadingProgress) =>
|
||||
loadingProgress == null
|
||||
? child
|
||||
: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
errorBuilder: (context, error, stackTrace) =>
|
||||
const Tooltip(
|
||||
message: "Error loading image",
|
||||
child: Icon(
|
||||
Icons.error,
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: ColoredBox(
|
||||
color: theme.scaffoldBackgroundColor,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
product.name,
|
||||
style: theme.textTheme.titleMedium,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
"4.5",
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
const Icon(Icons.star, color: Colors.orange),
|
||||
const Icon(Icons.star, color: Colors.orange),
|
||||
const Icon(Icons.star, color: Colors.orange),
|
||||
const Icon(Icons.star, color: Colors.orange),
|
||||
const Icon(Icons.star_half,
|
||||
color: Colors.orange),
|
||||
Text(
|
||||
"(3)",
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
"\$${product.price.toStringAsFixed(2)}",
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
Text(
|
||||
"Gratis bezorging door Amazon",
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
FilledButton(
|
||||
onPressed: () {
|
||||
productService.addProduct(product as MyProduct);
|
||||
},
|
||||
child: const Text("In winkelwagen"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// (RECOMMENDED) The shop that is initially selected.
|
||||
// Must be one of the shops in the [shops] list.
|
||||
initialShopId: getCategories().first.id,
|
||||
|
||||
// (RECOMMENDED) Localizations for the product page.
|
||||
localizations: const ProductPageLocalization(),
|
||||
|
||||
noContentBuilder: (context) => Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 128),
|
||||
child: Column(
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.warning,
|
||||
size: 48,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
Text(
|
||||
"Geen producten gevonden",
|
||||
style: theme.textTheme.titleLarge,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// (OPTIONAL) Appbar
|
||||
appBar: AppBar(
|
||||
title: const SizedBox(
|
||||
height: 40,
|
||||
child: SearchBar(
|
||||
hintText: "Search products",
|
||||
leading: Icon(
|
||||
Icons.search,
|
||||
color: Colors.black,
|
||||
),
|
||||
trailing: [
|
||||
Icon(
|
||||
Icons.fit_screen_outlined,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
context.go(homePage);
|
||||
},
|
||||
),
|
||||
bottom: AppBar(
|
||||
backgroundColor: const Color.fromRGBO(203, 237, 230, 1),
|
||||
title: Row(
|
||||
children: [
|
||||
const Icon(Icons.location_on_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Bestemming: ${streetName ?? "Mark - 1234AB Doetinchem Nederland"}",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
primary: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// (OPTIONAL): Initial build shop id that overrides the initialShop
|
||||
initialBuildShopId: initialBuildShopId,
|
||||
);
|
||||
},
|
||||
|
||||
// (REQUIRED): Shopping cart builder configuration
|
||||
shoppingCartBuilder: (BuildContext context) => ShoppingCartScreen(
|
||||
configuration: ShoppingCartConfig(
|
||||
// (REQUIRED) product service instance:
|
||||
productService: productService,
|
||||
|
||||
// (REQUIRED) product item builder:
|
||||
productItemBuilder: (context, locale, product) => ListTile(
|
||||
title: Text(product.name),
|
||||
subtitle: Text(product.price.toStringAsFixed(2)),
|
||||
leading: Image.network(
|
||||
product.imageUrl,
|
||||
errorBuilder: (context, error, stackTrace) => const Tooltip(
|
||||
message: "Error loading image",
|
||||
child: Icon(
|
||||
Icons.error,
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.remove),
|
||||
onPressed: () => productService.removeOneProduct(product),
|
||||
),
|
||||
Text("${product.quantity}"),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.add),
|
||||
onPressed: () => productService.addProduct(product),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// (OPTIONAL/REQUIRED) on confirm order callback:
|
||||
// Either use this callback or the placeOrderButtonBuilder.
|
||||
onConfirmOrder: (products) => onCompleteShoppingCart(context),
|
||||
|
||||
// (RECOMMENDED) localizations:
|
||||
localizations: const ShoppingCartLocalizations(),
|
||||
|
||||
/// (OPTIONAL) no content builder for when there are no products
|
||||
/// in the shopping cart.
|
||||
noContentBuilder: (context) => const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 128),
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.warning,
|
||||
),
|
||||
SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
Text(
|
||||
"Geen producten in winkelmandje",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// (OPTIONAL) custom appbar:
|
||||
appBar: AppBar(
|
||||
title: const Text("Shopping Cart"),
|
||||
leading: IconButton(
|
||||
icon: const Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
),
|
||||
onPressed: () {
|
||||
context.go(FlutterShoppingPathRoutes.shop);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// (REQUIRED): Configuration on what to do when the user story is
|
||||
// completed.
|
||||
onCompleteUserStory: (BuildContext context) {
|
||||
context.go(homePage);
|
||||
},
|
||||
|
||||
// (RECOMMENDED) Handle processing of the order details. This function
|
||||
// should return true if the order was processed successfully, otherwise
|
||||
// false.
|
||||
//
|
||||
// If this function is not provided, it is assumed that the order is
|
||||
// always processed successfully.
|
||||
//
|
||||
// Example use cases that could be implemented here:
|
||||
// - Sending and storing the order on a server,
|
||||
// - Processing payment (if the user decides to pay upfront).
|
||||
// - And many more...
|
||||
// onCompleteOrderDetails:
|
||||
// (BuildContext context, OrderResult orderDetails) async {
|
||||
// return true;
|
||||
// },
|
||||
);
|
8
example_amazon/lib/src/models/my_category.dart
Normal file
8
example_amazon/lib/src/models/my_category.dart
Normal file
|
@ -0,0 +1,8 @@
|
|||
import "package:flutter_product_page/flutter_product_page.dart";
|
||||
|
||||
class MyCategory extends ProductPageShop {
|
||||
const MyCategory({
|
||||
required super.id,
|
||||
required super.name,
|
||||
});
|
||||
}
|
24
example_amazon/lib/src/models/my_product.dart
Normal file
24
example_amazon/lib/src/models/my_product.dart
Normal file
|
@ -0,0 +1,24 @@
|
|||
import "package:flutter_product_page/flutter_product_page.dart";
|
||||
import "package:flutter_shopping_cart/flutter_shopping_cart.dart";
|
||||
|
||||
class MyProduct extends ShoppingCartProduct with ProductPageProduct {
|
||||
MyProduct({
|
||||
required super.id,
|
||||
required super.name,
|
||||
required super.price,
|
||||
required this.category,
|
||||
required this.imageUrl,
|
||||
});
|
||||
|
||||
@override
|
||||
final String category;
|
||||
|
||||
@override
|
||||
final String imageUrl;
|
||||
|
||||
@override
|
||||
final double? discountPrice = 0.0;
|
||||
|
||||
@override
|
||||
final bool hasDiscount = false;
|
||||
}
|
31
example_amazon/lib/src/routes.dart
Normal file
31
example_amazon/lib/src/routes.dart
Normal file
|
@ -0,0 +1,31 @@
|
|||
import "package:amazon/src/configuration/shopping_configuration.dart";
|
||||
import "package:amazon/src/ui/homepage.dart";
|
||||
import "package:amazon/src/utils/go_router.dart";
|
||||
import "package:flutter_shopping/flutter_shopping.dart";
|
||||
import "package:go_router/go_router.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
|
||||
const String homePage = "/";
|
||||
|
||||
final routerProvider = Provider<GoRouter>(
|
||||
(ref) => GoRouter(
|
||||
initialLocation: homePage,
|
||||
routes: [
|
||||
// Flutter Shopping Story Routes
|
||||
...getShoppingStoryRoutes(
|
||||
configuration: getFlutterShoppingConfiguration(),
|
||||
),
|
||||
|
||||
// Home Route
|
||||
GoRoute(
|
||||
name: "home",
|
||||
path: homePage,
|
||||
pageBuilder: (context, state) => buildScreenWithFadeTransition(
|
||||
context: context,
|
||||
state: state,
|
||||
child: const Homepage(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
89
example_amazon/lib/src/services/category_service.dart
Normal file
89
example_amazon/lib/src/services/category_service.dart
Normal file
|
@ -0,0 +1,89 @@
|
|||
import "package:amazon/src/models/my_category.dart";
|
||||
import "package:amazon/src/models/my_product.dart";
|
||||
import "package:flutter_product_page/flutter_product_page.dart";
|
||||
|
||||
Map<String, String> categories = {
|
||||
"Electronics": "Electronica",
|
||||
"Smart phones": "Telefoons",
|
||||
"TV's": "TV's",
|
||||
};
|
||||
|
||||
List<MyProduct> allProducts() => [
|
||||
MyProduct(
|
||||
id: "1",
|
||||
name:
|
||||
"Skar Audio Single 8\" Complete 1,200 Watt EVL Series Subwoofer Bass Package - Includes Loaded Enclosure with...",
|
||||
price: 2.99,
|
||||
category: categories["Electronics"]!,
|
||||
imageUrl:
|
||||
"https://m.media-amazon.com/images/I/710n3hnbfXL._AC_UY218_.jpg",
|
||||
),
|
||||
MyProduct(
|
||||
id: "2",
|
||||
name:
|
||||
"Frameo 10.1 Inch WiFi Digital Picture Frame, 1280x800 HD IPS Touch Screen Photo Frame Electronic, 32GB Memory, Auto...",
|
||||
price: 2.99,
|
||||
category: categories["Electronics"]!,
|
||||
imageUrl:
|
||||
"https://m.media-amazon.com/images/I/61O+aorCp0L._AC_UY218_.jpg",
|
||||
),
|
||||
MyProduct(
|
||||
id: "3",
|
||||
name:
|
||||
"STREBITO Electronics Precision Screwdriver Sets 142-Piece with 120 Bits Magnetic Repair Tool Kit for iPhone, MacBook,...",
|
||||
price: 1.99,
|
||||
category: categories["Electronics"]!,
|
||||
imageUrl:
|
||||
"https://m.media-amazon.com/images/I/81-C7lGtQsL._AC_UY218_.jpg",
|
||||
),
|
||||
MyProduct(
|
||||
id: "4",
|
||||
name:
|
||||
"Samsung Galaxy A15 (SM-155M/DSN), 128GB 6GB RAM, Dual SIM, Factory Unlocked GSM, International Version (Wall...",
|
||||
price: 1.99,
|
||||
category: categories["Smart phones"]!,
|
||||
imageUrl:
|
||||
"https://m.media-amazon.com/images/I/51rp0nqaPoL._AC_UY218_.jpg",
|
||||
),
|
||||
MyProduct(
|
||||
id: "5",
|
||||
name:
|
||||
"SAMSUNG Galaxy S24 Ultra Cell Phone, 512GB AI Smartphone, Unlocked Android, 50MP Zoom Camera, Long...",
|
||||
price: 1.99,
|
||||
category: categories["Smart phones"]!,
|
||||
imageUrl:
|
||||
"https://m.media-amazon.com/images/I/71ZoDT7a2wL._AC_UY218_.jpg",
|
||||
),
|
||||
];
|
||||
|
||||
List<MyCategory> getCategories() => <MyCategory>[
|
||||
MyCategory(id: "1", name: categories["Electronics"]!),
|
||||
MyCategory(id: "2", name: categories["Smart phones"]!),
|
||||
MyCategory(id: "3", name: categories["TV's"]!),
|
||||
const MyCategory(id: "4", name: "Monitoren"),
|
||||
const MyCategory(id: "5", name: "Speakers"),
|
||||
const MyCategory(id: "6", name: "Toetsenborden"),
|
||||
];
|
||||
|
||||
ProductPageContent getShopContent(String shopId) {
|
||||
var products = getProducts(shopId);
|
||||
return ProductPageContent(
|
||||
products: products,
|
||||
);
|
||||
}
|
||||
|
||||
List<MyProduct> getProducts(String categoryId) {
|
||||
if (categoryId == "1") {
|
||||
return allProducts();
|
||||
} else if (categoryId == "2") {
|
||||
return allProducts()
|
||||
.where((product) => product.category == categories["Smart phones"]!)
|
||||
.toList();
|
||||
} else if (categoryId == "3") {
|
||||
return allProducts()
|
||||
.where((product) => product.category == categories["TV's"]!)
|
||||
.toList();
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
20
example_amazon/lib/src/ui/homepage.dart
Normal file
20
example_amazon/lib/src/ui/homepage.dart
Normal file
|
@ -0,0 +1,20 @@
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter_shopping/flutter_shopping.dart";
|
||||
import "package:go_router/go_router.dart";
|
||||
|
||||
class Homepage extends StatelessWidget {
|
||||
const Homepage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Scaffold(
|
||||
body: Center(
|
||||
child: Badge(
|
||||
label: const Text("1"),
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.shopping_cart_outlined, size: 50),
|
||||
onPressed: () => context.go(FlutterShoppingPathRoutes.shop),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
26
example_amazon/lib/src/utils/go_router.dart
Normal file
26
example_amazon/lib/src/utils/go_router.dart
Normal file
|
@ -0,0 +1,26 @@
|
|||
import "package:flutter/material.dart";
|
||||
import "package:go_router/go_router.dart";
|
||||
|
||||
CustomTransitionPage buildScreenWithFadeTransition<T>({
|
||||
required BuildContext context,
|
||||
required GoRouterState state,
|
||||
required Widget child,
|
||||
}) =>
|
||||
CustomTransitionPage<T>(
|
||||
key: state.pageKey,
|
||||
child: child,
|
||||
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
|
||||
FadeTransition(opacity: animation, child: child),
|
||||
);
|
||||
|
||||
CustomTransitionPage buildScreenWithoutTransition<T>({
|
||||
required BuildContext context,
|
||||
required GoRouterState state,
|
||||
required Widget child,
|
||||
}) =>
|
||||
CustomTransitionPage<T>(
|
||||
key: state.pageKey,
|
||||
child: child,
|
||||
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
|
||||
child,
|
||||
);
|
43
example_amazon/lib/src/utils/theme.dart
Normal file
43
example_amazon/lib/src/utils/theme.dart
Normal file
|
@ -0,0 +1,43 @@
|
|||
import "package:flutter/material.dart";
|
||||
|
||||
ThemeData getTheme() => ThemeData(
|
||||
scaffoldBackgroundColor: const Color.fromRGBO(250, 249, 246, 1),
|
||||
textTheme: const TextTheme(
|
||||
labelMedium: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.black,
|
||||
),
|
||||
titleMedium: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Color.fromRGBO(60, 60, 59, 1),
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
inputDecorationTheme: const InputDecorationTheme(
|
||||
fillColor: Colors.white,
|
||||
),
|
||||
colorScheme: const ColorScheme.light(
|
||||
primary: Color.fromRGBO(161, 203, 211, 1),
|
||||
secondary: Color.fromRGBO(221, 235, 238, 1),
|
||||
surface: Color.fromRGBO(255, 255, 255, 1),
|
||||
),
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: Color.fromRGBO(161, 220, 218, 1),
|
||||
foregroundColor: Colors.black,
|
||||
titleTextStyle: TextStyle(
|
||||
fontSize: 28,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
filledButtonTheme: FilledButtonThemeData(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(
|
||||
Colors.yellow,
|
||||
),
|
||||
foregroundColor: WidgetStateProperty.all(
|
||||
Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
42
example_amazon/pubspec.yaml
Normal file
42
example_amazon/pubspec.yaml
Normal file
|
@ -0,0 +1,42 @@
|
|||
name: amazon
|
||||
description: "A new Flutter project."
|
||||
publish_to: 'none'
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: '>=3.4.1 <4.0.0'
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_hooks: ^0.20.0
|
||||
hooks_riverpod: ^2.1.1
|
||||
go_router: 12.1.3
|
||||
flutter_nested_categories:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_nested_categories
|
||||
ref: 0.0.1
|
||||
flutter_product_page:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_product_page
|
||||
ref: 1.3.3
|
||||
flutter_shopping_cart:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_shopping_cart
|
||||
ref: 1.1.1
|
||||
flutter_order_details:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_order_details
|
||||
ref: 1.0.1
|
||||
flutter_shopping:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_shopping
|
||||
ref: 1.0.6
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^3.0.0
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
Loading…
Reference in a new issue