import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:kantin_app/presentation/screens/features/confirm_order_page.dart'; class CartPage extends StatefulWidget { const CartPage({super.key}); @override State createState() => _CartPageState(); } class _CartPageState extends State { final List _items = [ CartItem( name: 'Nasi Ayam Geprek', price: 10000, quantity: 1, location: 'Kantin 1', imageUrl: 'assets/images/nasi_ayam.jpg', ), CartItem( name: 'Nasi Ayam Geprek', price: 10000, quantity: 1, location: 'Kantin 2', imageUrl: 'assets/images/nasi_ayam.jpg', ), ]; double get _totalPrice => _items.fold( 0, (sum, item) => sum + (item.price * item.quantity), ); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.white, elevation: 0, toolbarHeight: 88, leading: IconButton( icon: const Icon(Icons.arrow_back, color: Color(0xFF2196F3)), onPressed: () => Navigator.pop(context), ), title: const Text( 'Keranjang', style: TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: 20, ), ), centerTitle: false, ), body: Column( children: [ const SizedBox(height: 4), Expanded( child: ListView.builder( itemCount: _items.length, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), itemBuilder: (context, index) { final item = _items[index]; return Container( margin: const EdgeInsets.only(bottom: 4), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.08), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Padding( padding: const EdgeInsets.all(10), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: BorderRadius.circular(8), child: Image.asset( item.imageUrl, width: 64, height: 64, fit: BoxFit.cover, ), ), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item.location, style: TextStyle( color: Colors.grey[500], fontSize: 11, ), ), const SizedBox(height: 2), Text( item.name, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 15, ), ), const SizedBox(height: 2), Text( 'Rp ${item.price}', style: const TextStyle( fontWeight: FontWeight.w500, fontSize: 13, ), ), const SizedBox(height: 4), OutlinedButton.icon( onPressed: () {}, icon: const Icon(Icons.receipt_outlined, size: 14, color: Colors.grey), label: const Text( 'Catatan', style: TextStyle(fontSize: 11, color: Colors.black), ), style: OutlinedButton.styleFrom( side: BorderSide(color: Colors.grey[300]!), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0), minimumSize: const Size(0, 24), tapTargetSize: MaterialTapTargetSize.shrinkWrap, visualDensity: VisualDensity.compact, ), ), ], ), ), Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GestureDetector( onTap: () { setState(() { _items.removeAt(index); }); }, child: Container( decoration: BoxDecoration( color: Colors.white, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.15), blurRadius: 4, ), ], ), padding: const EdgeInsets.all(4), child: const Icon(Icons.delete_outline, color: Colors.grey, size: 18), ), ), const SizedBox(height: 18), Row( mainAxisSize: MainAxisSize.min, children: [ _buildCircleIcon( icon: Icons.remove, onTap: item.quantity > 1 ? () { setState(() { item.quantity--; }); } : null, ), Padding( padding: const EdgeInsets.symmetric(horizontal: 6), child: Text( '${item.quantity}', style: const TextStyle( fontSize: 15, fontWeight: FontWeight.bold, ), ), ), _buildCircleIcon( icon: Icons.add, onTap: () { setState(() { item.quantity++; }); }, ), ], ), ], ), ], ), ), ); }, ), ), Container( padding: const EdgeInsets.fromLTRB(16, 12, 16, 24), decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.1), spreadRadius: 1, blurRadius: 10, ), ], ), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text('Biaya Pengiriman', style: TextStyle(fontSize: 12, color: Colors.grey)), Text( '+ Rp 2.000', style: TextStyle( color: Colors.blue[700], fontWeight: FontWeight.bold, fontSize: 13, ), ), ], ), const SizedBox(height: 4), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Total', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 14, ), ), Text( 'Rp ${_totalPrice + 2000}', style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), ), ], ), const SizedBox(height: 12), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () { context.push('/confirm-order'); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF2196F3), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(24), ), elevation: 0, ), child: const Text('Pesan Sekarang', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), ), ), ], ), ), ], ), ); } Widget _buildCircleIcon({required IconData icon, VoidCallback? onTap}) { return GestureDetector( onTap: onTap, child: Container( width: 28, height: 28, decoration: BoxDecoration( color: onTap != null ? const Color(0xFF2196F3) : Colors.grey[200], shape: BoxShape.circle, ), child: Icon( icon, color: onTap != null ? Colors.white : Colors.grey, size: 18, ), ), ); } Route _createScaleRoute(Widget page) { return PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) => page, transitionsBuilder: (context, animation, secondaryAnimation, child) { final scale = Tween(begin: 0.8, end: 1.0).animate( CurvedAnimation(parent: animation, curve: Curves.easeOutBack), ); return ScaleTransition( scale: scale, child: child, ); }, transitionDuration: const Duration(milliseconds: 350), reverseTransitionDuration: const Duration(milliseconds: 250), ); } } class CartItem { final String name; final int price; int quantity; final String location; final String imageUrl; CartItem({ required this.name, required this.price, required this.quantity, required this.location, required this.imageUrl, }); }