From e1e702bd7692ed84d575e1f67cdf3a603d3ea65f Mon Sep 17 00:00:00 2001 From: efrilm Date: Fri, 19 Sep 2025 13:31:17 +0700 Subject: [PATCH] fix null --- .../settings_local_datasource.dart | 2 +- .../report/blocs/report/report_bloc.dart | 2 +- .../success/pages/success_order_page.dart | 1784 +++++++---------- 3 files changed, 770 insertions(+), 1018 deletions(-) diff --git a/lib/data/datasources/settings_local_datasource.dart b/lib/data/datasources/settings_local_datasource.dart index 3ff7fed..144e626 100644 --- a/lib/data/datasources/settings_local_datasource.dart +++ b/lib/data/datasources/settings_local_datasource.dart @@ -19,7 +19,7 @@ class SettingsLocalDatasource { return TaxModel( name: 'Tax', type: TaxType.pajak, - value: 11, + value: 0, ); } } diff --git a/lib/presentation/report/blocs/report/report_bloc.dart b/lib/presentation/report/blocs/report/report_bloc.dart index f8b8e2b..d9218c9 100644 --- a/lib/presentation/report/blocs/report/report_bloc.dart +++ b/lib/presentation/report/blocs/report/report_bloc.dart @@ -44,7 +44,7 @@ class ReportBloc extends Bloc { category .getOrElse( () => CategoryAnalyticResponseModel(success: false, data: null)) - .data!, + .data, profitLoss .getOrElse( () => ProfitLossResponseModel(success: false, data: null)) diff --git a/lib/presentation/success/pages/success_order_page.dart b/lib/presentation/success/pages/success_order_page.dart index 2c4cb55..05485dc 100644 --- a/lib/presentation/success/pages/success_order_page.dart +++ b/lib/presentation/success/pages/success_order_page.dart @@ -28,116 +28,7 @@ class SuccessOrderPage extends StatefulWidget { State createState() => _SuccessOrderPageState(); } -class _SuccessOrderPageState extends State - with TickerProviderStateMixin { - late AnimationController _mainController; - late AnimationController _successController; - late AnimationController _cardController; - late AnimationController _floatingController; - - late Animation _fadeInAnimation; - late Animation _scaleAnimation; - late Animation _successIconAnimation; - late Animation _slideUpAnimation; - late Animation _floatingAnimation; - late Animation _shimmerAnimation; - - @override - void initState() { - super.initState(); - - _mainController = AnimationController( - duration: const Duration(milliseconds: 1000), - vsync: this, - ); - - _successController = AnimationController( - duration: const Duration(milliseconds: 1500), - vsync: this, - ); - - _cardController = AnimationController( - duration: const Duration(milliseconds: 800), - vsync: this, - ); - - _floatingController = AnimationController( - duration: const Duration(seconds: 3), - vsync: this, - )..repeat(reverse: true); - - _fadeInAnimation = Tween( - begin: 0.0, - end: 1.0, - ).animate(CurvedAnimation( - parent: _mainController, - curve: const Interval(0.0, 0.6, curve: Curves.easeOut), - )); - - _scaleAnimation = Tween( - begin: 0.8, - end: 1.0, - ).animate(CurvedAnimation( - parent: _mainController, - curve: const Interval(0.2, 0.8, curve: Curves.elasticOut), - )); - - _successIconAnimation = Tween( - begin: 0.0, - end: 1.0, - ).animate(CurvedAnimation( - parent: _successController, - curve: Curves.elasticOut, - )); - - _slideUpAnimation = Tween( - begin: const Offset(0.0, 0.3), - end: Offset.zero, - ).animate(CurvedAnimation( - parent: _cardController, - curve: Curves.easeOutCubic, - )); - - _floatingAnimation = Tween( - begin: -5.0, - end: 5.0, - ).animate(CurvedAnimation( - parent: _floatingController, - curve: Curves.easeInOut, - )); - - _shimmerAnimation = Tween( - begin: -1.0, - end: 2.0, - ).animate(CurvedAnimation( - parent: _mainController, - curve: Curves.easeInOut, - )); - - // Start animations with staggered delays - _startAnimations(); - } - - void _startAnimations() async { - await Future.delayed(const Duration(milliseconds: 300)); - _mainController.forward(); - - await Future.delayed(const Duration(milliseconds: 500)); - _successController.forward(); - - await Future.delayed(const Duration(milliseconds: 700)); - _cardController.forward(); - } - - @override - void dispose() { - _mainController.dispose(); - _successController.dispose(); - _cardController.dispose(); - _floatingController.dispose(); - super.dispose(); - } - +class _SuccessOrderPageState extends State { @override Widget build(BuildContext context) { return Scaffold( @@ -155,30 +46,24 @@ class _SuccessOrderPageState extends State ], ), ), - child: FadeTransition( - opacity: _fadeInAnimation, - child: ScaleTransition( - scale: _scaleAnimation, - child: Padding( - padding: const EdgeInsets.all(24.0), - child: Row( - children: [ - // Left Panel - Success Message & Order Info - Expanded( - flex: 35, - child: _buildLeftPanel(), - ), - - const SizedBox(width: 16), - - // Right Panel - Order Details - Expanded( - flex: 65, - child: _buildRightPanel(), - ), - ], + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Row( + children: [ + // Left Panel - Success Message & Order Info + Expanded( + flex: 35, + child: _buildLeftPanel(), ), - ), + + const SizedBox(width: 16), + + // Right Panel - Order Details + Expanded( + flex: 65, + child: _buildRightPanel(), + ), + ], ), ), ), @@ -187,357 +72,296 @@ class _SuccessOrderPageState extends State } Widget _buildLeftPanel() { - return SlideTransition( - position: _slideUpAnimation, - child: 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 with Glassmorphism Effect - Expanded( - child: SingleChildScrollView( - child: Column( - children: [ - 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: [ - // Animated Success Icon with Floating Effect - AnimatedBuilder( - animation: _floatingAnimation, - builder: (context, child) { - return Transform.translate( - offset: Offset(0, _floatingAnimation.value), - child: ScaleTransition( - scale: _successIconAnimation, - child: 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 with Shimmer Effect - FadeTransition( - opacity: _fadeInAnimation, - child: ShaderMask( - shaderCallback: (bounds) { - return LinearGradient( - begin: Alignment.centerLeft, - end: Alignment.centerRight, - colors: const [ - AppColors.primary, - Colors.amber, - AppColors.primary, - ], - stops: [ - _shimmerAnimation.value - 1, - _shimmerAnimation.value, - _shimmerAnimation.value + 1, - ], - ).createShader(bounds); - }, - child: const Text( - 'Pesanan Berhasil!', - style: TextStyle( - fontSize: 26, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ), - ), - - const SizedBox(height: 12), - - FadeTransition( - opacity: _fadeInAnimation, - child: 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 - Padding( - padding: const EdgeInsets.all(24.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildSectionTitle('Informasi Pesanan'), - const SizedBox(height: 24), - - // Customer Card with Gradient Background - _buildInfoCard( - icon: Icons.person_outline_rounded, - title: 'Nama Pelanggan', - value: - widget.order.metadata?['customer_name'] ?? "-", - gradient: [ - Colors.blue.withOpacity(0.1), - Colors.purple.withOpacity(0.1), - ], - ), - - const SizedBox(height: 16), - - // Order Details Grid - Column( - children: [ - _buildInfoRow( - icon: Icons.receipt_long_outlined, - label: 'No. Pesanan', - value: widget.order.orderNumber ?? "-", - delay: 0.3, - ), - const SizedBox(height: 12), - _buildInfoRow( - icon: Icons.wallet_outlined, - label: 'Metode Pembayaran', - value: widget.paymentMethod ?? "-", - delay: 0.3, - ), - if (widget.order.tableNumber != "") ...[ - const SizedBox(height: 12), - _buildInfoRow( - icon: Icons.table_restaurant_outlined, - label: 'No. Meja', - value: widget.order.tableNumber ?? "-", - delay: 0.4, - ), - ], - const SizedBox(height: 12), - _buildInfoRow( - icon: Icons.access_time_rounded, - label: 'Waktu', - value: - (widget.order.createdAt ?? DateTime.now()) - .toFormattedDate3(), - delay: 0.5, - ), - ], - ), - ], - ), - ), - ], - ), - ), - ), - - // Total and Action Buttons - _buildBottomSection(), - ], - ), + 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), + ), + ], ), - ); - } - - Widget _buildRightPanel() { - return SlideTransition( - position: _slideUpAnimation, - child: 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 with Modern Design - 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( + child: Column( + children: [ + // Success Header with Glassmorphism Effect + Expanded( + child: SingleChildScrollView( + child: Column( children: [ - ScaleTransition( - scale: _successIconAnimation, - child: 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), + 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), + ], ), - child: Icon( - Icons.receipt_long_rounded, - color: AppColors.primary, - size: 28, + borderRadius: const BorderRadius.vertical( + top: Radius.circular(24), ), ), - ), - const SizedBox(width: 16), - Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, children: [ - FadeTransition( - opacity: _fadeInAnimation, - child: const Text( - 'Detail Pesanan', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, + // 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: 4), - FadeTransition( - opacity: _fadeInAnimation, - child: Text( - 'Ringkasan item yang dipesan', + + 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: Colors.grey.shade600, + color: AppColors.primary, + fontWeight: FontWeight.w500, ), + textAlign: TextAlign.center, ), ), ], ), ), - ScaleTransition( - scale: _scaleAnimation, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 16, vertical: 10), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - AppColors.primary, - AppColors.primary.withOpacity(0.8), + // Order Information Section + Padding( + padding: const EdgeInsets.all(24.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildSectionTitle('Informasi Pesanan'), + const SizedBox(height: 24), + + // Customer Card with Gradient Background + _buildInfoCard( + icon: Icons.person_outline_rounded, + title: 'Nama Pelanggan', + value: widget.order.metadata?['customer_name'] ?? "-", + gradient: [ + Colors.blue.withOpacity(0.1), + Colors.purple.withOpacity(0.1), ], ), - 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, + + const SizedBox(height: 16), + + // Order Details Grid + Column( + children: [ + _buildInfoRow( + icon: Icons.receipt_long_outlined, + label: 'No. Pesanan', + value: widget.order.orderNumber ?? "-", + ), + const SizedBox(height: 12), + _buildInfoRow( + icon: Icons.wallet_outlined, + label: 'Metode Pembayaran', + value: widget.paymentMethod, + ), + if (widget.order.tableNumber != "") ...[ + const SizedBox(height: 12), + _buildInfoRow( + icon: Icons.table_restaurant_outlined, + label: 'No. Meja', + value: widget.order.tableNumber ?? "-", + ), + ], + const SizedBox(height: 12), + _buildInfoRow( + icon: Icons.access_time_rounded, + label: 'Waktu', + value: (widget.order.createdAt ?? DateTime.now()) + .toFormattedDate3(), + ), + ], ), - ), + ], ), ), ], ), ), + ), - // Enhanced 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); - }, + // Total and Action Buttons + _buildBottomSection(), + ], + ), + ); + } + + Widget _buildRightPanel() { + 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 with Modern Design + 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, + ), + ), + ), + ], + ), + ), - // Enhanced Summary Footer - _buildSummaryFooter(), - ], - ), + // Enhanced 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); + }, + ), + ), + + // Enhanced Summary Footer + _buildSummaryFooter(), + ], ), ); } @@ -547,178 +371,159 @@ class _SuccessOrderPageState extends State final totalPrice = (item.product.price ?? 0) * item.quantity + (item.variant?.priceModifier ?? 0); - return TweenAnimationBuilder( - tween: Tween(begin: 0.0, end: 1.0), - duration: Duration(milliseconds: 600 + (index * 100)), - curve: Curves.easeOutCubic, - builder: (context, animation, child) { - return Transform.translate( - offset: Offset(0, 20 * (1 - animation)), - child: Opacity( - opacity: animation, - child: 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: [ - // Enhanced Product Image - Hero( - tag: 'product_${index}', - child: 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, - ), - ), - ], - ), + 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: [ + // Enhanced 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 FadeTransition( - opacity: _fadeInAnimation, - child: Text( - title, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), + return Text( + title, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, ), ); } @@ -729,55 +534,52 @@ class _SuccessOrderPageState extends State required String value, required List gradient, }) { - return ScaleTransition( - scale: _scaleAnimation, - child: 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, - ), + return Container( + width: double.infinity, + padding: const EdgeInsets.all(20.0), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: gradient, ), - 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, + 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, ), - ], - ), + ), + ], ), ); } @@ -786,80 +588,66 @@ class _SuccessOrderPageState extends State required IconData icon, required String label, required String value, - required double delay, Color? valueColor, bool showBadge = false, }) { - return TweenAnimationBuilder( - tween: Tween(begin: 0.0, end: 1.0), - duration: Duration(milliseconds: (800 + delay * 1000).round()), - curve: Curves.easeOutCubic, - builder: (context, animation, child) { - return Transform.translate( - offset: Offset(0, 10 * (1 - animation)), - child: Opacity( - opacity: animation, - child: 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, - ), - ), - ], + 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, + ), + ), + ], ); } @@ -883,47 +671,42 @@ class _SuccessOrderPageState extends State child: Column( children: [ // Total Amount with Enhanced Styling - ScaleTransition( - scale: _scaleAnimation, - child: 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( - (widget.order.totalAmount ?? 0) - .toString() - .currencyFormatRpV2, - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.primary, - ), - ), + 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( + (widget.order.totalAmount ?? 0).toString().currencyFormatRpV2, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: AppColors.primary, + ), + ), + ], ), ), @@ -933,123 +716,103 @@ class _SuccessOrderPageState extends State Row( children: [ Expanded( - child: TweenAnimationBuilder( - tween: Tween(begin: 0.0, end: 1.0), - duration: const Duration(milliseconds: 800), - curve: Curves.easeOutCubic, - builder: (context, animation, child) { - return Transform.scale( - scale: animation, - 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, - ), - ), - ), + 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: TweenAnimationBuilder( - tween: Tween(begin: 0.0, end: 1.0), - duration: const Duration(milliseconds: 1000), - curve: Curves.easeOutCubic, - builder: (context, animation, child) { - return Transform.scale( - scale: animation, - 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 { - onPrintRecipt( - context, - order: widget.order, - paymentMethod: widget.paymentMethod, - nominalBayar: widget.paymentMethod == "Cash" - ? widget.nominalBayar - : widget.order.totalAmount ?? 0, - kembalian: widget.nominalBayar - - (widget.order.totalAmount ?? 0), - productQuantity: widget.productQuantity, - ); - onPrint( - context, - productQuantity: widget.productQuantity, - order: widget.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, - ), - ), - ], - ), - ), - ), + 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 { + onPrintRecipt( + context, + order: widget.order, + paymentMethod: widget.paymentMethod, + nominalBayar: widget.paymentMethod == "Cash" + ? widget.nominalBayar + : widget.order.totalAmount ?? 0, + kembalian: widget.nominalBayar - + (widget.order.totalAmount ?? 0), + productQuantity: widget.productQuantity, + ); + onPrint( + context, + productQuantity: widget.productQuantity, + order: widget.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, + ), + ), + ], + ), + ), + ), ), ), ], @@ -1060,165 +823,154 @@ class _SuccessOrderPageState extends State } Widget _buildSummaryFooter() { - return SlideTransition( - position: _slideUpAnimation, - child: 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), - ), + 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, + ], ), - 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, - ], - ), + 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 - FadeTransition( - opacity: _fadeInAnimation, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + // Subtotal Row + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( 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, - ), - ), - ], + Icon( + Icons.shopping_cart_outlined, + size: 16, + color: Colors.grey.shade600, ), + const SizedBox(width: 8), Text( - (widget.order.totalAmount ?? 0) - .toString() - .currencyFormatRpV2, - style: const TextStyle( + 'Subtotal (${widget.productQuantity.length} items)', + style: TextStyle( fontSize: 14, - fontWeight: FontWeight.w600, + color: Colors.grey.shade600, + fontWeight: FontWeight.w500, ), ), ], ), - ), - - const SizedBox(height: 16), - - // Total Payment Row with Enhanced Styling - ScaleTransition( - scale: _scaleAnimation, - child: 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, - ), + Text( + (widget.order.totalAmount ?? 0).toString().currencyFormatRpV2, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + ), + ], + ), + + const SizedBox(height: 16), + + // Total Payment Row with Enhanced Styling + 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: [ - 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, - ), + padding: const EdgeInsets.all(6), decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - AppColors.primary, - AppColors.primary.withOpacity(0.8), - ], - ), + color: AppColors.primary.withOpacity(0.2), borderRadius: BorderRadius.circular(8), - boxShadow: [ - BoxShadow( - color: AppColors.primary.withOpacity(0.3), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], ), - child: Text( - (widget.order.totalAmount ?? 0) - .toString() - .currencyFormatRpV2, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), + 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( + (widget.order.totalAmount ?? 0) + .toString() + .currencyFormatRpV2, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + ), + ], ), - ], - ), + ), + ], ), ); }