Alışveriş Sepeti: Ödeme
Coddy'nin Flutter Journey'sinin Durum Yönetimi bölümünün bir parçası. Ders 27 / 27.
Son parça ödeme işlemidir. Tek dokunuşla üç şey olur: sepet boşalır, siparişi onaylayan bir mesaj gösterilir ve müşteri, rozetin artık görünmediği mağazaya geri döner.
Sepeti boşaltmak, bildirimciye eklenen bir yöntemdir ve yeni, boş bir liste atar:
void clear() {
state = [];
}Sepette hiçbir şey yokken ödeme yapmak mantıklı değildir, bu yüzden düğmeyi devre dışı bırak. onPressed değeri null olan bir düğmeye basılamaz:
onPressed: cart.isEmpty ? null : () { ... },Şimdiye kadar yaptıklarına bir bak: iki ekran, bir rozet ve bir toplam; hepsi tek bir sepeti okuyor ve hiçbir değer bir ekrandan diğerine aktarılmıyor. İşte bu durum yönetimidir.
Görev
OrtaSepet ekranındaki toplam tutarın altına bir Check out düğmesi ekle:
- Sepet boşken devre dışı bırakılır.
- Düğmeye basıldığında, yeni bir
clear()yöntemiyle sepeti boşaltır,Order placed!mesajını içeren birSnackBargösterir ve mağazaya geri döner.
Kendin dene
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class Product {
const Product(this.name, this.price);
final String name;
final double price;
}
const products = [
Product('Apple', 0.5),
Product('Bread', 2.25),
Product('Cheese', 4),
Product('Milk', 1.2),
];
class Cart extends Notifier<List<Product>> {
@override
List<Product> build() => [];
void add(Product product) {
state = [...state, product];
}
void removeAt(int index) {
final copy = [...state];
copy.removeAt(index);
state = copy;
}
}
final cartProvider = NotifierProvider<Cart, List<Product>>(Cart.new);
final totalProvider = Provider((ref) {
final cart = ref.watch(cartProvider);
return cart.fold(0.0, (sum, product) => sum + product.price);
});
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: ShopPage(),
);
}
}
class ShopPage extends ConsumerWidget {
const ShopPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final cart = ref.watch(cartProvider);
return Scaffold(
appBar: AppBar(
title: const Text('Shop'),
actions: [
IconButton(
icon: Badge(
label: Text('${cart.length}'),
isLabelVisible: cart.isNotEmpty,
child: const Icon(Icons.shopping_cart),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const CartScreen()),
);
},
),
],
),
body: ListView(
children: [
for (final product in products)
ListTile(
title: Text(product.name),
subtitle: Text('\$${product.price.toStringAsFixed(2)}'),
trailing: IconButton(
icon: const Icon(Icons.add_shopping_cart),
onPressed: () {
ref.read(cartProvider.notifier).add(product);
},
),
),
],
),
);
}
}
class CartScreen extends ConsumerWidget {
const CartScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final cart = ref.watch(cartProvider);
final total = ref.watch(totalProvider);
return Scaffold(
appBar: AppBar(title: const Text('Your cart')),
bottomNavigationBar: Padding(
padding: const EdgeInsets.all(24),
child: Text(
'Total: \$${total.toStringAsFixed(2)}',
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
),
body: cart.isEmpty
? const Center(child: Text('Your cart is empty'))
: ListView(
children: [
for (var i = 0; i < cart.length; i++)
ListTile(
title: Text(cart[i].name),
subtitle: Text('\$${cart[i].price.toStringAsFixed(2)}'),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
ref.read(cartProvider.notifier).removeAt(i);
},
),
),
],
),
);
}
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Durum Yönetimi bölümündeki tüm dersler
2Modeller için Dart
Sınıflarınızda MetotlarSınıflarınızda Getter'larBir Alanı Gizli Tutunfold ile Bir Listeyi Toplayın5Proje: Alışveriş Sepeti
Alışveriş Sepeti: Sepete EklemeAlışveriş Sepeti: RozetKendi başına pratik yap: Online Flutter derleyicisi