Skip to content

Instantly share code, notes, and snippets.

@prakhart111
Created March 10, 2025 13:49
Show Gist options
  • Save prakhart111/0e869f81db7bf311d8edec3c1647617e to your computer and use it in GitHub Desktop.
Save prakhart111/0e869f81db7bf311d8edec3c1647617e to your computer and use it in GitHub Desktop.
Snippet created via Remix API
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
scaffoldBackgroundColor: Colors.grey[100],
),
home: const ShoppingApp(),
);
}
}
class ShoppingApp extends StatefulWidget {
const ShoppingApp({super.key});
@override
State<ShoppingApp> createState() => _ShoppingAppState();
}
class _ShoppingAppState extends State<ShoppingApp> {
final List<Product> products = [
Product(
name: 'Sneakers',
price: 99.99,
image: 'https://placehold.co/600x400.png',
description: 'Comfortable sports shoes',
),
Product(
name: 'T-Shirt',
price: 29.99,
image: 'https://placehold.co/600x400.png',
description: 'Cotton casual t-shirt',
),
Product(
name: 'Jeans',
price: 59.99,
image: 'https://placehold.co/600x400.png',
description: 'Classic blue jeans',
),
];
List<Product> cart = [];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Shopping App'),
actions: [
Stack(
children: [
IconButton(
icon: const Icon(Icons.shopping_cart),
onPressed: () {
showCart();
},
),
if (cart.isNotEmpty)
Positioned(
right: 8,
top: 8,
child: Container(
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(10),
),
constraints: const BoxConstraints(
minWidth: 16,
minHeight: 16,
),
child: Text(
'${cart.length}',
style: const TextStyle(
color: Colors.white,
fontSize: 10,
),
textAlign: TextAlign.center,
),
),
),
],
),
],
),
body: GridView.builder(
padding: const EdgeInsets.all(16),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 0.75,
crossAxisSpacing: 16,
mainAxisSpacing: 16,
),
itemCount: products.length,
itemBuilder: (context, index) {
return ProductCard(
product: products[index],
onAddToCart: () {
setState(() {
cart.add(products[index]);
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('${products[index].name} added to cart'),
duration: const Duration(seconds: 1),
),
);
},
);
},
),
);
}
void showCart() {
showModalBottomSheet(
context: context,
builder: (context) {
return Container(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Shopping Cart',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
Expanded(
child: cart.isEmpty
? const Center(
child: Text('Your cart is empty'),
)
: ListView.builder(
itemCount: cart.length,
itemBuilder: (context, index) {
return CartItem(
product: cart[index],
onRemove: () {
setState(() {
cart.removeAt(index);
});
Navigator.pop(context);
showCart();
},
);
},
),
),
if (cart.isNotEmpty)
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Total: \$${cart.fold(0.0, (sum, item) => sum + item.price).toStringAsFixed(2)}',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
ElevatedButton(
onPressed: () {
setState(() {
cart.clear();
});
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Order placed successfully!'),
),
);
},
child: const Text('Checkout'),
),
],
),
),
],
),
);
},
);
}
}
class Product {
final String name;
final double price;
final String image;
final String description;
Product({
required this.name,
required this.price,
required this.image,
required this.description,
});
}
class ProductCard extends StatelessWidget {
final Product product;
final VoidCallback onAddToCart;
const ProductCard({
super.key,
required this.product,
required this.onAddToCart,
});
@override
Widget build(BuildContext context) {
return Card(
elevation: 2,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Image.network(
product.image,
fit: BoxFit.cover,
width: double.infinity,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
product.name,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
Text(
'\$${product.price.toStringAsFixed(2)}',
style: const TextStyle(
fontSize: 14,
color: Colors.blue,
),
),
const SizedBox(height: 8),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: onAddToCart,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 8),
),
child: const Text('Add to Cart'),
),
),
],
),
),
],
),
);
}
}
class CartItem extends StatelessWidget {
final Product product;
final VoidCallback onRemove;
const CartItem({
super.key,
required this.product,
required this.onRemove,
});
@override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.only(bottom: 8),
child: ListTile(
leading: Image.network(
product.image,
width: 50,
height: 50,
fit: BoxFit.cover,
),
title: Text(product.name),
subtitle: Text('\$${product.price.toStringAsFixed(2)}'),
trailing: IconButton(
icon: const Icon(Icons.remove_circle_outline),
onPressed: onRemove,
color: Colors.red,
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment