141 lines
4.0 KiB
Dart
141 lines
4.0 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:mobile_scanner/mobile_scanner.dart';
|
|
import 'package:inventory_system/screens/user/scan/scan_result_user.dart';
|
|
import 'package:inventory_system/screens/title_bar.dart';
|
|
import 'package:inventory_system/screens/nav_bar.dart';
|
|
import 'package:inventory_system/screens/bottom_nav_bar.dart';
|
|
|
|
class ScanUserScreen extends StatefulWidget {
|
|
const ScanUserScreen({super.key});
|
|
|
|
@override
|
|
State<ScanUserScreen> createState() => _ScanUserScreenState();
|
|
}
|
|
|
|
class _ScanUserScreenState extends State<ScanUserScreen> {
|
|
int _selectedIndex = 1;
|
|
bool _isProcessing = false;
|
|
|
|
void _onDetect(BarcodeCapture capture) async {
|
|
if (_isProcessing) return;
|
|
|
|
final codes = capture.barcodes;
|
|
if (codes.isEmpty) return;
|
|
|
|
final value = codes.first.rawValue;
|
|
if (value == null || value.isEmpty) return;
|
|
|
|
_isProcessing = true;
|
|
|
|
await Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => ScanResultUserScreen(scannedCode: value.trim()),
|
|
),
|
|
);
|
|
|
|
// brief debounce to avoid flood
|
|
await Future.delayed(const Duration(milliseconds: 500));
|
|
_isProcessing = false;
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: const Color(0xFFF5F5F7),
|
|
appBar: const TitleBar(title: 'Scan Item (User)'),
|
|
drawer: const NavBar(isAdmin: false, selectedScreen: AppScreen.scan),
|
|
body: Stack(
|
|
fit: StackFit.expand,
|
|
children: [
|
|
// 1. Add Padding around the camera view
|
|
Padding(
|
|
padding: const EdgeInsets.all(38.38), // Adjust the padding as you need
|
|
child: ClipRRect(
|
|
// 2. (Optional) Add rounded corners to the camera view
|
|
borderRadius: BorderRadius.circular(24.0),
|
|
child: MobileScanner(
|
|
fit: BoxFit.cover, // Use BoxFit.cover for a better aspect ratio
|
|
onDetect: _onDetect,
|
|
),
|
|
),
|
|
),
|
|
_ScannerOverlay(),
|
|
Positioned(
|
|
bottom: 16,
|
|
left: 0,
|
|
right: 0,
|
|
child: Text(
|
|
'Place the code inside the frame',
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.bold,
|
|
shadows: [
|
|
Shadow(
|
|
blurRadius: 10.0,
|
|
color: Colors.black.withOpacity(0.5),
|
|
offset: const Offset(0, 0),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
bottomNavigationBar: BottomNavBar(
|
|
selectedIndex: _selectedIndex,
|
|
onItemTapped: (index) {
|
|
setState(() => _selectedIndex = index);
|
|
if (index == 0) {
|
|
Navigator.pop(context);
|
|
}
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ScannerOverlay extends StatelessWidget {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return IgnorePointer(
|
|
child: CustomPaint(
|
|
painter: _OverlayPainter(),
|
|
size: Size.infinite,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _OverlayPainter extends CustomPainter {
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
final paint = Paint()
|
|
..color = Colors.white
|
|
..style = PaintingStyle.stroke
|
|
..strokeWidth = 3;
|
|
|
|
final double padding = 48;
|
|
final rect = RRect.fromRectAndRadius(
|
|
Rect.fromLTWH(padding, padding, size.width - padding * 2, size.height - padding * 2),
|
|
const Radius.circular(12),
|
|
);
|
|
|
|
final bg = Paint()..color = Colors.black.withOpacity(0.5);
|
|
final clearPaint = Paint()..blendMode = BlendMode.clear;
|
|
final path = Path()..addRRect(rect);
|
|
|
|
canvas.saveLayer(Offset.zero & size, Paint());
|
|
canvas.drawRect(Offset.zero & size, bg);
|
|
canvas.drawPath(path, clearPaint);
|
|
canvas.restore();
|
|
|
|
canvas.drawRRect(rect, paint);
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
|
}
|