import 'package:audioplayers/audioplayers.dart'; import 'package:business_panel/presentation/order/bloc/order_bloc.dart'; import 'package:business_panel/presentation/widgets/success_popup.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:jwt_decoder/jwt_decoder.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:vibration/vibration.dart'; class BarcodeScannerPage extends StatefulWidget { final String discountId; const BarcodeScannerPage({super.key, required this.discountId}); @override State createState() => _BarcodeScannerPageState(); } class _BarcodeScannerPageState extends State { final MobileScannerController _scannerController = MobileScannerController(); final AudioPlayer _audioPlayer = AudioPlayer(); bool _isProcessing = false; void _handleBarcode(BarcodeCapture capture) { if (_isProcessing) return; setState(() => _isProcessing = true); final String? rawValue = capture.barcodes.first.rawValue; if (rawValue == null) { _showError("بارکد نامعتبر است."); return; } try { final Map decodedToken = JwtDecoder.decode(rawValue); final String? userId = decodedToken['userID']; final String? discountIdFromToken = decodedToken['discountID']; if (userId == null || discountIdFromToken == null) { _showError("اطلاعات لازم در بارکد یافت نشد."); return; } if (discountIdFromToken != widget.discountId) { _showError("این بارکد برای این تخفیف معتبر نیست."); return; } context.read().add( SubmitOrder(discountId: discountIdFromToken, userId: userId), ); } catch (e) { _showError("فرمت بارکد صحیح نیست."); } } void _showError(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(message), backgroundColor: Colors.red), ); setState(() => _isProcessing = false); } @override void dispose() { _scannerController.dispose(); _audioPlayer.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("اسکن بارکد مشتری")), body: BlocListener( listener: (context, state) async { if (state is OrderSubmissionSuccess) { if (await Vibration.hasVibrator() ?? false) { Vibration.vibrate(duration: 200); } await _audioPlayer.play(AssetSource('sounds/short-success-sound-glockenspiel-treasure-video-game-6346.mp3')); await showSuccessDialog(context, message: state.message); Navigator.of(context).pop(); } else if (state is OrderSubmissionFailure) { _showError(state.error); } }, child: Stack( children: [ MobileScanner( controller: _scannerController, onDetect: _handleBarcode, ), Center( child: Container( width: 250, height: 250, decoration: BoxDecoration( border: Border.all(color: Colors.green, width: 4), borderRadius: BorderRadius.circular(12), ), ), ), BlocBuilder( builder: (context, state) { if (state is OrderSubmissionInProgress) { return Container( color: Colors.black.withOpacity(0.5), child: const Center( child: CircularProgressIndicator(color: Colors.white), ), ); } return const SizedBox.shrink(); }, ), ], ), ), ); } }