import 'package:flutter/material.dart'; import '../utils/theme.dart'; class PosSellingScreen extends StatefulWidget { final String shopName; final int sessionId; const PosSellingScreen({super.key, required this.shopName, required this.sessionId}); @override State createState() => _PosSellingScreenState(); } class _PosSellingScreenState extends State { // Mock Data final List> _foodProducts = [ {'name': 'Bacon Burger', 'price': 12.0, 'image': 'https://plus.unsplash.com/premium_photo-1661331777080-459247d853e3?q=80&w=300&auto=format&fit=crop'}, {'name': 'Cheese Burger', 'price': 10.5, 'image': 'https://images.unsplash.com/photo-1568901346375-23c9450c58cd?q=80&w=300&auto=format&fit=crop'}, {'name': 'Pizza Margherita', 'price': 15.0, 'image': 'https://images.unsplash.com/photo-1513104890138-7c749659a591?q=80&w=300&auto=format&fit=crop'}, {'name': 'Pizza Veggie', 'price': 14.0, 'image': 'https://images.unsplash.com/photo-1604382354936-07c5d9983bd3?q=80&w=300&auto=format&fit=crop'}, {'name': 'Pasta Carbonara', 'price': 13.5, 'image': 'https://images.unsplash.com/photo-1612874742237-6526221588e3?q=80&w=300&auto=format&fit=crop'}, {'name': 'Club Sandwich', 'price': 9.0, 'image': 'https://images.unsplash.com/photo-1597255682855-667d4ccf044d?q=80&w=300&auto=format&fit=crop'}, ]; final List> _drinkProducts = [ {'name': 'Coca-Cola', 'price': 3.0, 'image': 'https://images.unsplash.com/photo-1622483767028-3f66f32aef97?q=80&w=300&auto=format&fit=crop'}, {'name': 'Water 500ml', 'price': 2.0, 'image': 'https://images.unsplash.com/photo-1616118132534-381148898bb6?q=80&w=300&auto=format&fit=crop'}, {'name': 'Espresso', 'price': 2.5, 'image': 'https://images.unsplash.com/photo-1514432324607-a09d9b4aefdd?q=80&w=300&auto=format&fit=crop'}, {'name': 'Green Tea', 'price': 3.5, 'image': 'https://images.unsplash.com/photo-1627435601361-ec25f5b1d0e5?q=80&w=300&auto=format&fit=crop'}, {'name': 'Milkshake', 'price': 5.0, 'image': 'https://images.unsplash.com/photo-1579954115563-e72bf1381629?q=80&w=300&auto=format&fit=crop'}, ]; String _selectedCategory = 'Food'; // 'Food' or 'Drinks' List> _cartItems = []; void _addToCart(Map product) { setState(() { final index = _cartItems.indexWhere((item) => item['name'] == product['name']); if (index != -1) { _cartItems[index]['qty'] += 1; } else { _cartItems.add({ 'name': product['name'], 'price': product['price'], 'qty': 1, }); } }); } void _removeFromCart(int index) { setState(() { _cartItems.removeAt(index); }); } void _decrementCartItem(int index) { setState(() { if (_cartItems[index]['qty'] > 1) { _cartItems[index]['qty'] -= 1; } else { _cartItems.removeAt(index); } }); } double get _totalAmount { return _cartItems.fold(0.0, (sum, item) => sum + (item['price'] * item['qty'])); } int get _totalItems { return _cartItems.fold(0, (sum, item) => sum + (item['qty'] as int)); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF0F4F7), body: LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth > 700) { return _buildWideLayout(); } else { return _buildMobileLayout(); } }, ), ); } Widget _buildWideLayout() { return Row( children: [ // Left: Register/Cart Expanded( flex: 4, child: _buildCartPanel(isMobile: false), ), // Right: Products Expanded( flex: 6, child: _buildProductPanel(), ), ], ); } Widget _buildMobileLayout() { return Stack( children: [ // Product Panel Full Screen Column( children: [ Expanded(child: _buildProductPanel()), const SizedBox(height: 80), // Space for bottom bar ], ), // Cart Summary Bottom Bar Positioned( left: 0, right: 0, bottom: 0, child: _buildMobileBottomBar(), ), ], ); } Widget _buildMobileBottomBar() { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: const Color(0xFF2C3E50), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.2), blurRadius: 10, offset: const Offset(0, -2))], borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), ), child: Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text('$_totalItems Items', style: const TextStyle(color: Colors.white70, fontSize: 13)), const SizedBox(height: 4), Text('₹ ${_totalAmount.toStringAsFixed(2)}', style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 20)), ], ), const Spacer(), ElevatedButton.icon( onPressed: _showMobileCartModal, icon: const Icon(Icons.shopping_cart_outlined), label: const Text('View Cart'), style: ElevatedButton.styleFrom( backgroundColor: AppTheme.secondaryColor, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), ), ], ), ); } void _showMobileCartModal() { showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (context) => Container( height: MediaQuery.of(context).size.height * 0.85, decoration: const BoxDecoration( color: Color(0xFF2C3E50), borderRadius: BorderRadius.vertical(top: Radius.circular(24)), ), child: Column( children: [ // Handle Container(width: 40, height: 4, margin: const EdgeInsets.symmetric(vertical: 12), decoration: BoxDecoration(color: Colors.white24, borderRadius: BorderRadius.circular(2))), Expanded(child: _buildCartPanel(isMobile: true)), ], ), ), ); } Widget _buildCartPanel({required bool isMobile}) { return Container( color: const Color(0xFF2C3E50), child: Column( children: [ // Header Container( padding: const EdgeInsets.fromLTRB(20, 20, 20, 10), decoration: const BoxDecoration( border: Border(bottom: BorderSide(color: Colors.white10)), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text('Current Order', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18)), if (isMobile) IconButton(onPressed: () => Navigator.pop(context), icon: const Icon(Icons.keyboard_arrow_down, color: Colors.white70)) else IconButton(onPressed: () => Navigator.pop(context), icon: const Icon(Icons.close, color: Colors.white70)) ], ), ), // Cart Items Expanded( child: _cartItems.isEmpty ? const Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.shopping_cart_outlined, color: Colors.white24, size: 48), SizedBox(height: 16), Text('Cart is empty', style: TextStyle(color: Colors.white54)), ] ) ) : ListView.builder( padding: const EdgeInsets.all(12), itemCount: _cartItems.length, itemBuilder: (context, index) { final item = _cartItems[index]; return Container( margin: const EdgeInsets.only(bottom: 8), decoration: BoxDecoration(color: Colors.white.withOpacity(0.05), borderRadius: BorderRadius.circular(12)), child: ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), title: Text(item['name'], style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w600)), subtitle: Text('${item['qty']} x ₹${item['price']}', style: const TextStyle(color: Colors.white70)), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ Text('₹${(item['price'] * item['qty']).toStringAsFixed(2)}', style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), const SizedBox(width: 8), IconButton( icon: const Icon(Icons.remove_circle_outline, size: 22, color: Colors.orangeAccent), tooltip: 'Reduce Quantity', onPressed: () => _decrementCartItem(index), ), IconButton( icon: const Icon(Icons.add_circle_outline, size: 22, color: Colors.greenAccent), tooltip: 'Add Quantity', onPressed: () => _addToCart(item), ), ], ), ), ); }, ), ), // Totals & Actions Container( padding: const EdgeInsets.all(20), decoration: const BoxDecoration(color: Color(0xFF233140)), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text('Total', style: TextStyle(color: Colors.white, fontSize: 18)), Text('₹ ${_totalAmount.toStringAsFixed(2)}', style: const TextStyle(color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold)), ], ), const SizedBox(height: 20), Row( children: [ Expanded( child: ElevatedButton( onPressed: () {}, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFFE91E63), padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), child: const Text('Customer', style: TextStyle(color: Colors.white)), ) ), const SizedBox(width: 12), Expanded( child: ElevatedButton( onPressed: _showPaymentModal, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF4CAF50), padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), child: const Text('Payment', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), ) ), ], ) ], ), ) ], ), ); } Widget _buildProductPanel() { return Container( color: const Color(0xFFF0F4F7), child: Column( children: [ // Top Bar Container( padding: const EdgeInsets.fromLTRB(16, 50, 16, 16), // Top padding for status bar if mobile color: Colors.white, child: Column( children: [ Row( children: [ // Back button here too for convenience? Or relying on Cart back if (MediaQuery.of(context).size.width <= 700) IconButton(onPressed: () => Navigator.pop(context), icon: const Icon(Icons.arrow_back)), Expanded( child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: [ _buildCategoryTab('Food', Icons.lunch_dining, const Color(0xFFF8BBD0), const Color(0xFFE91E63)), const SizedBox(width: 12), _buildCategoryTab('Drinks', Icons.local_drink, const Color(0xFFC8E6C9), const Color(0xFF4CAF50)), ], ), ), ), ], ), ], ), ), // Grid Expanded( child: Padding( padding: const EdgeInsets.all(16), child: GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: MediaQuery.of(context).size.width > 900 ? 5 : (MediaQuery.of(context).size.width > 600 ? 4 : 2), childAspectRatio: 0.8, crossAxisSpacing: 16, mainAxisSpacing: 16, ), itemCount: _selectedCategory == 'Food' ? _foodProducts.length : _drinkProducts.length, itemBuilder: (context, index) { final product = _selectedCategory == 'Food' ? _foodProducts[index] : _drinkProducts[index]; return _buildProductCard(product); }, ), ), ), ], ), ); } Widget _buildCategoryTab(String title, IconData icon, Color bgColor, Color textColor) { final bool isSelected = _selectedCategory == title; return GestureDetector( onTap: () => setState(() => _selectedCategory = title), child: AnimatedContainer( duration: const Duration(milliseconds: 200), padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), decoration: BoxDecoration( color: isSelected ? bgColor : Colors.grey[100], borderRadius: BorderRadius.circular(12), border: isSelected ? Border.all(color: textColor.withOpacity(0.5), width: 1.5) : null, ), child: Row( children: [ Icon(icon, color: isSelected ? textColor : Colors.grey[600], size: 20), const SizedBox(width: 8), Text(title, style: TextStyle(color: isSelected ? textColor : Colors.grey[800], fontWeight: FontWeight.w700)), ], ), ), ); } Widget _buildProductCard(Map product) { return GestureDetector( onTap: () => _addToCart(product), child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow(color: Colors.black.withOpacity(0.04), blurRadius: 12, offset: const Offset(0, 4)), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded( child: ClipRRect( borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), child: Image.network( product['image'], fit: BoxFit.cover, errorBuilder: (ctx, err, stack) => Container( color: Colors.grey[100], child: const Icon(Icons.restaurant, color: Colors.grey, size: 30) ), ), ), ), Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(product['name'], style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: Color(0xFF2D3748)), maxLines: 1, overflow: TextOverflow.ellipsis), const SizedBox(height: 6), Text('₹ ${product['price']}', style: const TextStyle(color: Color(0xFF38A169), fontWeight: FontWeight.bold, fontSize: 15)), ], ), ) ], ), ), ); } void _showPaymentModal() { showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (context) => Container( height: MediaQuery.of(context).size.height * 0.9, decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), child: Column( children: [ // Header Container( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey[200]!)), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text('Payment', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), IconButton(onPressed: () => Navigator.pop(context), icon: const Icon(Icons.close)), ], ), ), Expanded( child: Row( children: [ // Payment Methods (Left) Expanded( flex: 4, child: Container( color: const Color(0xFFF8F9FA), child: ListView( padding: const EdgeInsets.all(20), children: [ _buildPaymentMethod('Cash', Icons.money, true), const SizedBox(height: 10), _buildPaymentMethod('Bank', Icons.credit_card, false), const SizedBox(height: 10), _buildPaymentMethod('Customer Account', Icons.person, false), ], ), ), ), // Payment Details & Numpad (Right) Expanded( flex: 6, child: Padding( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Total Display Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Remaining to Pay', style: TextStyle(color: Colors.grey[600], fontSize: 14, fontWeight: FontWeight.w500)), const SizedBox(height: 8), Text('₹ ${_totalAmount.toStringAsFixed(2)}', style: const TextStyle(fontSize: 42, fontWeight: FontWeight.bold, color: Color(0xFF2D3748))), ], ), const Spacer(), // Validate Button SizedBox( height: 56, child: ElevatedButton.icon( onPressed: () { Navigator.pop(context); // Close Payment _processOrderSuccess(); }, icon: const Icon(Icons.check_circle_outline), label: const Text('Validate Order', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF4CAF50), foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), elevation: 4, ), ), ), ], ), ), ), ], ), ), ], ), ), ); } Widget _buildPaymentMethod(String name, IconData icon, bool selected) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: selected ? Colors.white : Colors.transparent, borderRadius: BorderRadius.circular(12), border: selected ? Border.all(color: AppTheme.primaryColor, width: 2) : Border.all(color: Colors.grey[300]!), boxShadow: selected ? [BoxShadow(color: AppTheme.primaryColor.withOpacity(0.1), blurRadius: 10)] : [], ), child: Row( children: [ Icon(icon, color: selected ? AppTheme.primaryColor : Colors.grey[600]), const SizedBox(width: 12), Text(name, style: TextStyle( fontWeight: FontWeight.bold, color: selected ? AppTheme.primaryColor : Colors.grey[800], fontSize: 16 )), const Spacer(), if (selected) const Icon(Icons.check_circle, color: AppTheme.primaryColor), ], ), ); } void _processOrderSuccess() { setState(() { _cartItems.clear(); }); showDialog( context: context, builder: (context) => AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), content: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.check_circle, color: Colors.green, size: 64), const SizedBox(height: 16), const Text('Order Validated!', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), const SizedBox(height: 8), const Text('Receipt has been printed.', style: TextStyle(color: Colors.grey)), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Next Order', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), ) ], ), ); } }