import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:url_launcher/url_launcher.dart'; import '../providers/order_provider.dart'; import '../theme.dart'; import '../l10n/app_localizations.dart'; class ScanResultPage extends ConsumerStatefulWidget { final String scanCode; const ScanResultPage({super.key, required this.scanCode}); @override ConsumerState createState() => _ScanResultPageState(); } class _ScanResultPageState extends ConsumerState { bool _showActionSheet = false; @override void initState() { super.initState(); Future.microtask(() { ref.read(orderProvider.notifier).scanVerify(widget.scanCode); }); } void _showVerifyDialog() { final l10n = AppLocalizations.of(context)!; final order = ref.read(orderProvider).currentOrder; if (order == null || !order.canVerify) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(l10n.notVerifiable)), ); return; } showModalBottomSheet( context: context, backgroundColor: Colors.transparent, isScrollControlled: true, builder: (context) { return Container( padding: const EdgeInsets.all(24), decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(24)), ), child: SafeArea( child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: 40, height: 4, decoration: BoxDecoration( color: AppColors.divider, borderRadius: BorderRadius.circular(2), ), ), const SizedBox(height: 24), Container( width: 64, height: 64, decoration: BoxDecoration( color: AppColors.primary.withOpacity(0.1), shape: BoxShape.circle, ), child: const Icon(Icons.qr_code_scanner, color: AppColors.primary, size: 32), ), const SizedBox(height: 20), Text( l10n.confirmVerify, style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: AppColors.textPrimary, ), ), const SizedBox(height: 8), Text( '${l10n.orderNo}: ${order.orderNo}', style: TextStyle(fontSize: 14, color: AppColors.textSecondary), ), const SizedBox(height: 4), Text( '${l10n.customerName}: ${order.customerName}', style: TextStyle(fontSize: 14, color: AppColors.textSecondary), ), const SizedBox(height: 4), Text( '${l10n.amount}: ¥${order.amount.toStringAsFixed(2)}', style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: AppColors.primary, ), ), const SizedBox(height: 24), Row( children: [ Expanded( child: OutlinedButton( onPressed: () => Navigator.of(context).pop(), style: OutlinedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), side: BorderSide(color: AppColors.divider), ), child: Text(l10n.cancel), ), ), const SizedBox(width: 16), Expanded( child: ElevatedButton( onPressed: () { Navigator.of(context).pop(); _doVerify(); }, style: ElevatedButton.styleFrom( backgroundColor: AppColors.primary, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Text(l10n.confirmVerify), ), ), ], ), ], ), ), ); }, ); } void _doVerify() { final l10n = AppLocalizations.of(context)!; final order = ref.read(orderProvider).currentOrder; if (order == null) return; ref.read(orderProvider.notifier).verifyOrder(order.id).then((_) { final state = ref.read(orderProvider); if (state.verifySuccess) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(l10n.verifySuccess), backgroundColor: AppColors.success, behavior: SnackBarBehavior.floating, ), ); ref.read(orderProvider.notifier).clearVerifySuccess(); setState(() => _showActionSheet = false); } }); } Future _makePhoneCall() async { final order = ref.read(orderProvider).currentOrder; if (order == null) return; final phone = order.customerPhone.replaceAll('*', '0'); final uri = Uri.parse('tel:$phone'); if (await canLaunchUrl(uri)) { await launchUrl(uri); } } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; final state = ref.watch(orderProvider); final order = state.currentOrder; if (state.isLoading || order == null) { return Scaffold( backgroundColor: AppColors.background, appBar: AppBar(title: Text(l10n.scanResult)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const CircularProgressIndicator(), const SizedBox(height: 16), Text(l10n.scanning, style: TextStyle(color: AppColors.textSecondary)), ], ), ), ); } return Scaffold( backgroundColor: AppColors.background, appBar: AppBar( title: Text(l10n.scanResult), leading: IconButton( icon: const Icon(Icons.close), onPressed: () => context.go('/home'), ), ), body: Stack( children: [ SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildResultHeader(order, l10n), const SizedBox(height: 20), _buildOrderInfoCard(order, l10n), const SizedBox(height: 20), _buildCustomerCard(order, l10n), const SizedBox(height: 100), ], ), ), if (order.canVerify) Positioned( left: 0, right: 0, bottom: 0, child: _buildBottomActions(order, l10n), ), ], ), ); } Widget _buildResultHeader(order, AppLocalizations l10n) { return Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( gradient: AppGradients.primary, borderRadius: BorderRadius.circular(20), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(20), ), child: Text( order.statusText, style: const TextStyle( color: Colors.white, fontSize: 13, fontWeight: FontWeight.w600, ), ), ), ], ), const SizedBox(height: 16), Text( l10n.scanSuccess, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(height: 8), Text( '${l10n.orderNo}: ${order.orderNo}', style: TextStyle( fontSize: 14, color: Colors.white.withOpacity(0.85), fontFamily: 'monospace', ), ), ], ), ); } Widget _buildOrderInfoCard(order, AppLocalizations l10n) { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.circular(16), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n.orderInfo, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.textPrimary, ), ), const SizedBox(height: 16), _buildInfoRow(l10n.product, order.productName, Icons.shopping_bag_outlined), const Divider(height: 20), _buildInfoRow(l10n.quantity, 'x${order.quantity}', Icons.confirmation_number_outlined), const Divider(height: 20), _buildInfoRow(l10n.amount, '¥${order.amount.toStringAsFixed(2)}', Icons.payments_outlined), if (order.verifyCode != null) ...[ const Divider(height: 20), _buildInfoRow(l10n.verifyCode, order.verifyCode!, Icons.qr_code), ], ], ), ); } Widget _buildCustomerCard(order, AppLocalizations l10n) { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.circular(16), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n.customerInfo, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.textPrimary, ), ), const SizedBox(height: 16), _buildInfoRow(l10n.name, order.customerName, Icons.person_outline), const Divider(height: 20), _buildInfoRow(l10n.phone, order.customerPhone, Icons.phone_outlined), ], ), ); } Widget _buildInfoRow(String label, String value, IconData icon) { return Row( children: [ Icon(icon, size: 18, color: AppColors.primary), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle(fontSize: 12, color: AppColors.textTertiary), ), const SizedBox(height: 2), Text( value, style: TextStyle( fontSize: 15, fontWeight: FontWeight.w500, color: AppColors.textPrimary, ), ), ], ), ), ], ); } Widget _buildBottomActions(order, AppLocalizations l10n) { return Container( padding: const EdgeInsets.fromLTRB(20, 16, 20, 28), decoration: BoxDecoration( color: AppColors.surface, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.08), blurRadius: 20, offset: const Offset(0, -4), ), ], ), child: SafeArea( child: Row( children: [ Expanded( child: OutlinedButton.icon( onPressed: _makePhoneCall, icon: const Icon(Icons.phone, size: 20), label: Text(l10n.contactCustomer), style: OutlinedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), ), ), ), ), const SizedBox(width: 16), Expanded( child: ElevatedButton.icon( onPressed: _showVerifyDialog, icon: const Icon(Icons.check_circle, size: 20), label: Text(l10n.verify), style: ElevatedButton.styleFrom( backgroundColor: AppColors.success, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), ), ), ), ), ], ), ), ); } }