diff --git a/lib/pages/scan_page.dart b/lib/pages/scan_page.dart new file mode 100644 index 0000000..f289441 --- /dev/null +++ b/lib/pages/scan_page.dart @@ -0,0 +1,127 @@ +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:pad_scanner/models/scan_record.dart'; +import 'package:pad_scanner/services/scanner_service.dart'; +import 'package:pad_scanner/services/api_service.dart'; +import 'package:pad_scanner/pages/settings_page.dart'; + +class ScanPage extends StatefulWidget { + const ScanPage({super.key}); + + @override + State createState() => _ScanPageState(); +} + +class _ScanPageState extends State { + final _scannerService = ScannerService(); + final _apiService = ApiService(); + final _records = []; + String _status = 'Waiting for scan...'; + + @override + void initState() { + super.initState(); + _startListening(); + } + + void _startListening() { + _scannerService.scanResults.listen((result) async { + final record = ScanRecord( + barcode: result.barcode, + codeType: result.codeType, + timestamp: DateTime.now(), + ); + + setState(() { + _records.insert(0, record); + _status = 'Sending...'; + }); + + final prefs = await SharedPreferences.getInstance(); + final url = prefs.getString('api_url') ?? ''; + + if (url.isEmpty) { + setState(() { + record.status = SendStatus.failed; + _status = 'No URL configured. Go to Settings.'; + }); + return; + } + + final ok = await _apiService.sendScanData( + url, + barcode: record.barcode, + codeType: record.codeType, + ); + + if (mounted) { + setState(() { + record.status = ok ? SendStatus.success : SendStatus.failed; + _status = ok ? 'Sent successfully' : 'Send failed'; + }); + } + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('PAD Scanner'), + actions: [ + IconButton( + icon: const Icon(Icons.settings), + onPressed: () => Navigator.push( + context, + MaterialPageRoute(builder: (_) => const SettingsPage()), + ), + ), + ], + ), + body: Column( + children: [ + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + color: Theme.of(context).colorScheme.surfaceContainerHighest, + child: Text( + _status, + style: Theme.of(context).textTheme.titleMedium, + textAlign: TextAlign.center, + ), + ), + Expanded( + child: _records.isEmpty + ? const Center( + child: Text( + 'No scans yet.\nPress the scan button on the device.', + textAlign: TextAlign.center)) + : ListView.builder( + itemCount: _records.length, + itemBuilder: (context, index) { + final r = _records[index]; + return ListTile( + title: Text(r.barcode), + subtitle: Text( + '${r.codeType} ${r.timestamp.toLocal().toIso8601String().substring(0, 19)}'), + trailing: Icon( + r.status == SendStatus.success + ? Icons.check_circle + : r.status == SendStatus.failed + ? Icons.error + : Icons.hourglass_empty, + color: r.status == SendStatus.success + ? Colors.green + : r.status == SendStatus.failed + ? Colors.red + : Colors.orange, + ), + ); + }, + ), + ), + ], + ), + ); + } +}