added categories, import export, settings
This commit is contained in:
+24
-21
@@ -1,4 +1,4 @@
|
||||
/// Single screen: capture or pick a receipt photo, then show raw OCR text.
|
||||
/// Capture or pick a receipt photo, then review parsed line items.
|
||||
library;
|
||||
|
||||
import 'dart:io';
|
||||
@@ -8,16 +8,23 @@ import 'package:flutter/services.dart';
|
||||
import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
import 'products_screen.dart';
|
||||
import 'review_screen.dart';
|
||||
import 'services/app_settings.dart';
|
||||
import 'services/product_repository.dart';
|
||||
import 'services/receipt_parser.dart';
|
||||
import 'utils/constants.dart';
|
||||
import 'utils/supermarkets.dart';
|
||||
import 'widgets/settings_button.dart';
|
||||
|
||||
class ScanScreen extends StatefulWidget {
|
||||
const ScanScreen({super.key, required this.repository});
|
||||
const ScanScreen({
|
||||
super.key,
|
||||
required this.repository,
|
||||
this.onTripSaved,
|
||||
});
|
||||
|
||||
final ProductRepository repository;
|
||||
final VoidCallback? onTripSaved;
|
||||
|
||||
@override
|
||||
State<ScanScreen> createState() => _ScanScreenState();
|
||||
@@ -27,6 +34,7 @@ class _ScanScreenState extends State<ScanScreen> {
|
||||
final ImagePicker _picker = ImagePicker();
|
||||
|
||||
String _extractedText = '';
|
||||
String? _imagePath;
|
||||
bool _busy = false;
|
||||
String? _error;
|
||||
|
||||
@@ -81,6 +89,7 @@ class _ScanScreenState extends State<ScanScreen> {
|
||||
_busy = true;
|
||||
_error = null;
|
||||
_extractedText = '';
|
||||
_imagePath = imagePath;
|
||||
});
|
||||
|
||||
final recognizer = TextRecognizer(script: TextRecognitionScript.latin);
|
||||
@@ -114,23 +123,23 @@ class _ScanScreenState extends State<ScanScreen> {
|
||||
Future<void> _openReview(String rawText) async {
|
||||
final items = ReceiptParser.parse(rawText);
|
||||
if (!mounted) return;
|
||||
await Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
final names =
|
||||
SettingsScope.maybeOf(context)?.supermarkets.map((s) => s.name) ??
|
||||
kSupermarkets;
|
||||
final saved = await Navigator.of(context).push<bool>(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => ReviewScreen(
|
||||
items: items,
|
||||
rawText: rawText,
|
||||
repository: widget.repository,
|
||||
imagePath: _imagePath,
|
||||
supermarketNames: names.toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _openProducts() {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => ProductsScreen(repository: widget.repository),
|
||||
),
|
||||
);
|
||||
if (saved == true && mounted) {
|
||||
widget.onTripSaved?.call();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -140,13 +149,7 @@ class _ScanScreenState extends State<ScanScreen> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text(kAppName),
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: 'Products',
|
||||
onPressed: _openProducts,
|
||||
icon: const Icon(Icons.inventory_2_outlined),
|
||||
),
|
||||
],
|
||||
actions: const [SettingsButton()],
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
@@ -220,7 +223,7 @@ class _ResultPane extends StatelessWidget {
|
||||
if (text.isEmpty) {
|
||||
return Center(
|
||||
child: Text(
|
||||
'Take a photo of a shopping receipt, or pick one from the gallery.\n\nExtracted text will show up here.',
|
||||
'Take a photo of a shopping receipt, or pick one from the gallery.\n\nConfirmed trips show up in Shop log.',
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.bodyLarge,
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user