import 'package:enaklo_pos/core/constants/colors.dart'; import 'package:enaklo_pos/core/extensions/build_context_ext.dart'; import 'package:enaklo_pos/core/extensions/date_time_ext.dart'; import 'package:enaklo_pos/core/extensions/string_ext.dart'; import 'package:enaklo_pos/core/function/app_function.dart'; import 'package:enaklo_pos/data/models/response/order_response_model.dart'; import 'package:enaklo_pos/presentation/home/models/product_quantity.dart'; import 'package:enaklo_pos/presentation/home/pages/dashboard_page.dart'; import 'package:enaklo_pos/presentation/sales/blocs/order_loader/order_loader_bloc.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class SuccessSaveOrderPage extends StatefulWidget { final List productQuantity; final String orderId; const SuccessSaveOrderPage({ super.key, required this.orderId, required this.productQuantity, }); @override State createState() => _SuccessSaveOrderPageState(); } class _SuccessSaveOrderPageState extends State { int totalPrice = 0; getPrice() { setState(() { totalPrice = widget.productQuantity.fold( 0, (previousValue, element) => previousValue + (element.product.price! * element.quantity) + (element.variant?.priceModifier ?? 0), ); }); } @override void initState() { super.initState(); context .read() .add(OrderLoaderEvent.getById(widget.orderId)); getPrice(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColors.background, body: SafeArea( child: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ AppColors.primary.withOpacity(0.05), AppColors.background, AppColors.background, ], ), ), child: BlocBuilder( builder: (context, state) { return state.maybeWhen( orElse: () => SizedBox.shrink(), loading: () => Center( child: CircularProgressIndicator(), ), loadedDetail: (order) { return Padding( padding: const EdgeInsets.all(24.0), child: Row( children: [ // Left Panel - Success Message & Order Info Expanded( flex: 35, child: _buildLeftPanel(order), ), const SizedBox(width: 16), // Right Panel - Order Details Expanded( flex: 65, child: _buildRightPanel(order), ), ], ), ); }, ); }, ), ), ), ); } Widget _buildLeftPanel(Order order) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( color: AppColors.primary.withOpacity(0.1), blurRadius: 30, offset: const Offset(0, 10), ), ], ), child: Column( children: [ // Success Header Container( width: double.infinity, padding: const EdgeInsets.all(32.0), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ AppColors.primary.withOpacity(0.1), AppColors.primary.withOpacity(0.05), ], ), borderRadius: const BorderRadius.vertical( top: Radius.circular(24), ), ), child: Column( children: [ // Success Icon Container( padding: const EdgeInsets.all(20.0), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ AppColors.primary, AppColors.primary.withOpacity(0.8), ], ), shape: BoxShape.circle, boxShadow: [ BoxShadow( color: AppColors.primary.withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 10), ), ], ), child: const Icon( Icons.check_rounded, size: 48, color: Colors.white, ), ), const SizedBox(height: 24), // Success Title const Text( 'Pesanan Berhasil!', style: TextStyle( fontSize: 26, fontWeight: FontWeight.bold, color: AppColors.primary, ), ), const SizedBox(height: 12), Container( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 8, ), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(20), ), child: const Text( 'Pesanan telah diterima dan sedang diproses', style: TextStyle( fontSize: 14, color: AppColors.primary, fontWeight: FontWeight.w500, ), textAlign: TextAlign.center, ), ), ], ), ), // Order Information Section Expanded( child: Padding( padding: const EdgeInsets.all(24.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildSectionTitle('Informasi Pesanan'), const SizedBox(height: 24), // Customer Card _buildInfoCard( icon: Icons.person_outline_rounded, title: 'Nama Pelanggan', value: order.metadata?['customer_name'] ?? "-", gradient: [ Colors.blue.withOpacity(0.1), Colors.purple.withOpacity(0.1), ], ), const SizedBox(height: 16), // Order Details Expanded( child: Column( children: [ _buildInfoRow( icon: Icons.receipt_long_outlined, label: 'No. Pesanan', value: order.orderNumber ?? "-", ), const SizedBox(height: 12), _buildInfoRow( icon: Icons.table_restaurant_outlined, label: 'No. Meja', value: order.tableNumber ?? "-", ), const SizedBox(height: 12), _buildInfoRow( icon: Icons.access_time_rounded, label: 'Waktu', value: (order.createdAt ?? DateTime.now()) .toFormattedDate3(), ), const SizedBox(height: 12), _buildInfoRow( icon: Icons.check_circle_outline, label: 'Status Pembayaran', value: 'Lunas', valueColor: Colors.green, showBadge: true, ), ], ), ), ], ), ), ), // Total and Action Buttons _buildBottomSection(order), ], ), ); } Widget _buildRightPanel(Order order) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.08), blurRadius: 30, offset: const Offset(0, 10), ), ], ), child: Column( children: [ // Header Container( width: double.infinity, padding: const EdgeInsets.all(24.0), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ AppColors.background, Colors.grey.shade50, ], ), borderRadius: const BorderRadius.vertical( top: Radius.circular(24), ), ), child: Row( children: [ Container( padding: const EdgeInsets.all(12.0), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColors.primary.withOpacity(0.2), AppColors.primary.withOpacity(0.1), ], ), borderRadius: BorderRadius.circular(16.0), ), child: Icon( Icons.receipt_long_rounded, color: AppColors.primary, size: 28, ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Detail Pesanan', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4), Text( 'Ringkasan item yang dipesan', style: TextStyle( fontSize: 14, color: Colors.grey.shade600, ), ), ], ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColors.primary, AppColors.primary.withOpacity(0.8), ], ), borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: AppColors.primary.withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: Text( '${widget.productQuantity.length} Items', style: const TextStyle( fontSize: 13, color: Colors.white, fontWeight: FontWeight.bold, ), ), ), ], ), ), // Product List Expanded( child: ListView.separated( padding: const EdgeInsets.all(24.0), itemCount: widget.productQuantity.length, separatorBuilder: (context, index) => const SizedBox(height: 12), itemBuilder: (context, index) { return _buildProductCard(index); }, ), ), // Summary Footer _buildSummaryFooter(order), ], ), ); } Widget _buildProductCard(int index) { final item = widget.productQuantity[index]; final totalPrice = (item.product.price ?? 0) * item.quantity + (item.variant?.priceModifier ?? 0); return Container( padding: const EdgeInsets.all(16.0), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Colors.grey.shade50, Colors.white, ], ), borderRadius: BorderRadius.circular(16.0), border: Border.all( color: Colors.grey.withOpacity(0.1), width: 1, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.04), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Row( children: [ // Product Image Container( width: 70, height: 70, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ AppColors.primary.withOpacity(0.2), AppColors.primary.withOpacity(0.1), ], ), borderRadius: BorderRadius.circular(16.0), boxShadow: [ BoxShadow( color: AppColors.primary.withOpacity(0.2), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: Icon( Icons.restaurant_rounded, color: AppColors.primary, size: 28, ), ), const SizedBox(width: 16), // Product Details Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item.product.name ?? "-", style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 6), Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, ), decoration: BoxDecoration( color: Colors.grey.shade100, borderRadius: BorderRadius.circular(8), ), child: Text( ((item.product.price ?? 0) + (item.variant?.priceModifier ?? 0)) .toString() .currencyFormatRpV2, style: TextStyle( fontSize: 14, color: Colors.grey.shade700, fontWeight: FontWeight.w500, ), ), ), ], ), ), const SizedBox(width: 16), // Quantity and Total Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColors.primary, AppColors.primary.withOpacity(0.8), ], ), borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: AppColors.primary.withOpacity(0.3), blurRadius: 6, offset: const Offset(0, 2), ), ], ), child: Text( '${item.quantity}x', style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Colors.white, ), ), ), const SizedBox(height: 8), Text( totalPrice.toString().currencyFormatRpV2, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: AppColors.primary, ), ), ], ), ], ), ); } Widget _buildSectionTitle(String title) { return Text( title, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ); } Widget _buildInfoCard({ required IconData icon, required String title, required String value, required List gradient, }) { return Container( width: double.infinity, padding: const EdgeInsets.all(20.0), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: gradient, ), borderRadius: BorderRadius.circular(16.0), border: Border.all( color: Colors.white.withOpacity(0.3), width: 1, ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( icon, size: 20, color: AppColors.primary, ), const SizedBox(width: 8), Text( title, style: TextStyle( fontSize: 12, color: Colors.grey.shade600, fontWeight: FontWeight.w500, ), ), ], ), const SizedBox(height: 8), Text( value, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: AppColors.primary, ), ), ], ), ); } Widget _buildInfoRow({ required IconData icon, required String label, required String value, Color? valueColor, bool showBadge = false, }) { return Row( children: [ Icon( icon, size: 18, color: Colors.grey.shade600, ), const SizedBox(width: 12), Expanded( child: Text( label, style: TextStyle( fontSize: 14, color: Colors.grey.shade600, ), ), ), if (showBadge && valueColor != null) Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, ), decoration: BoxDecoration( color: valueColor.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.check_circle, size: 14, color: valueColor, ), const SizedBox(width: 4), Text( value, style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: valueColor, ), ), ], ), ) else Text( value, style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: valueColor ?? Colors.black87, ), ), ], ); } Widget _buildBottomSection(Order order) { return Container( width: double.infinity, padding: const EdgeInsets.all(24.0), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.grey.shade50, Colors.white, ], ), borderRadius: const BorderRadius.vertical( bottom: Radius.circular(24), ), ), child: Column( children: [ // Total Amount Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ AppColors.primary.withOpacity(0.1), AppColors.primary.withOpacity(0.05), ], ), borderRadius: BorderRadius.circular(16), border: Border.all( color: AppColors.primary.withOpacity(0.2), width: 1, ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Total Pembayaran', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), Text( totalPrice.toString().currencyFormatRpV2, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: AppColors.primary, ), ), ], ), ), const SizedBox(height: 24), // Action Buttons Row( children: [ Expanded( child: Container( height: 50, decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), border: Border.all( color: AppColors.primary.withOpacity(0.3), width: 2, ), ), child: Material( color: Colors.transparent, borderRadius: BorderRadius.circular(14), child: InkWell( borderRadius: BorderRadius.circular(14), onTap: () { context.push(DashboardPage()); }, child: const Center( child: Text( 'Kembali ke Beranda', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: AppColors.primary, ), ), ), ), ), ), ), const SizedBox(width: 16), Expanded( child: Container( height: 50, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.centerLeft, end: Alignment.centerRight, colors: [ AppColors.primary, AppColors.primary.withOpacity(0.8), ], ), borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: AppColors.primary.withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: Material( color: Colors.transparent, borderRadius: BorderRadius.circular(16), child: InkWell( borderRadius: BorderRadius.circular(16), onTap: () async { onPrint( context, productQuantity: widget.productQuantity, order: order, ); }, child: const Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.print_rounded, color: Colors.white, size: 20, ), SizedBox(width: 8), Text( 'Cetak Struk', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white, ), ), ], ), ), ), ), ), ], ), ], ), ); } Widget _buildSummaryFooter(Order order) { return Container( width: double.infinity, padding: const EdgeInsets.all(24.0), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.grey.shade50, Colors.white, ], ), borderRadius: const BorderRadius.vertical( bottom: Radius.circular(24), ), ), child: Column( children: [ // Decorative Divider Container( height: 1, margin: const EdgeInsets.only(bottom: 20), decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.transparent, AppColors.primary.withOpacity(0.3), Colors.transparent, ], ), ), ), // Subtotal Row Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Icon( Icons.shopping_cart_outlined, size: 16, color: Colors.grey.shade600, ), const SizedBox(width: 8), Text( 'Subtotal (${widget.productQuantity.length} items)', style: TextStyle( fontSize: 14, color: Colors.grey.shade600, fontWeight: FontWeight.w500, ), ), ], ), Text( totalPrice.toString().currencyFormatRpV2, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, ), ), ], ), const SizedBox(height: 16), // Total Payment Row Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ AppColors.primary.withOpacity(0.1), AppColors.primary.withOpacity(0.05), ], ), borderRadius: BorderRadius.circular(12), border: Border.all( color: AppColors.primary.withOpacity(0.2), width: 1, ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Container( padding: const EdgeInsets.all(6), decoration: BoxDecoration( color: AppColors.primary.withOpacity(0.2), borderRadius: BorderRadius.circular(8), ), child: Icon( Icons.payments_rounded, size: 16, color: AppColors.primary, ), ), const SizedBox(width: 12), const Text( 'Total Pembayaran', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ], ), Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6, ), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColors.primary, AppColors.primary.withOpacity(0.8), ], ), borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: AppColors.primary.withOpacity(0.3), blurRadius: 4, offset: const Offset(0, 2), ), ], ), child: Text( totalPrice.toString().currencyFormatRpV2, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white, ), ), ), ], ), ), ], ), ); } }