2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-28 05:26:47 +00:00

Adds "barcode" field handler for API forms

This commit is contained in:
Oliver 2021-10-03 11:36:41 +11:00
parent 38e4735f77
commit 6288088a65
4 changed files with 118 additions and 5 deletions

View File

@ -7,6 +7,7 @@ import "package:date_field/date_field.dart";
import "package:inventree/api.dart"; import "package:inventree/api.dart";
import "package:inventree/app_colors.dart"; import "package:inventree/app_colors.dart";
import 'package:inventree/barcode.dart';
import "package:inventree/helpers.dart"; import "package:inventree/helpers.dart";
import "package:inventree/inventree/part.dart"; import "package:inventree/inventree/part.dart";
import "package:inventree/inventree/sentry.dart"; import "package:inventree/inventree/sentry.dart";
@ -269,7 +270,7 @@ class APIFormField {
} }
// Construct a widget for this input // Construct a widget for this input
Widget constructField() { Widget constructField(BuildContext context) {
switch (type) { switch (type) {
case "string": case "string":
case "url": case "url":
@ -288,6 +289,8 @@ class APIFormField {
return _constructFileField(); return _constructFileField();
case "date": case "date":
return _constructDateField(); return _constructDateField();
case "barcode":
return _constructBarcodeField(context);
default: default:
return ListTile( return ListTile(
title: Text( title: Text(
@ -300,6 +303,52 @@ class APIFormField {
} }
} }
// Field for capturing a barcode
Widget _constructBarcodeField(BuildContext context) {
TextEditingController controller = TextEditingController();
String barcode = (value ?? "").toString();
if (barcode.isEmpty) {
barcode = L10().barcodeNotAssigned;
}
controller.text = barcode;
return InputDecorator(
decoration: InputDecoration(
labelText: required ? label + "*" : label,
labelStyle: _labelStyle(),
helperText: helpText,
helperStyle: _helperStyle(),
hintText: placeholderText,
),
child: ListTile(
title: TextField(
readOnly: true,
controller: controller,
),
trailing: IconButton(
icon: FaIcon(FontAwesomeIcons.qrcode),
onPressed: () async {
var handler = UniqueBarcodeHandler((String hash) {
print("Scanned barcode: " + hash);
});
Navigator.push(
context,
MaterialPageRoute(builder: (context) => InvenTreeQRView(handler)
)
);
},
),
)
);
}
// Field for displaying and selecting dates // Field for displaying and selecting dates
Widget _constructDateField() { Widget _constructDateField() {
@ -937,7 +986,7 @@ class _APIFormWidgetState extends State<APIFormWidget> {
} }
} }
widgets.add(field.constructField()); widgets.add(field.constructField(context));
if (field.hasErrors()) { if (field.hasErrors()) {
for (String error in field.errorMessages()) { for (String error in field.errorMessages()) {

View File

@ -305,7 +305,7 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler {
} }
).then((result) { ).then((result) {
if (result) { if (result) {
failureTone(); successTone();
Navigator.of(context).pop(); Navigator.of(context).pop();
@ -315,7 +315,7 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler {
icon: FontAwesomeIcons.qrcode icon: FontAwesomeIcons.qrcode
); );
} else { } else {
successTone(); failureTone();
showSnackIcon( showSnackIcon(
L10().barcodeNotAssigned, L10().barcodeNotAssigned,
@ -464,6 +464,63 @@ class StockLocationScanInItemsHandler extends BarcodeHandler {
} }
class UniqueBarcodeHandler extends BarcodeHandler {
/*
* Barcode handler for finding a "unique" barcode (one that does not match an item in the database)
*/
UniqueBarcodeHandler(this.callback);
// Callback function when a "unique" barcode hash is found
final Function(String) callback;
@override
String getOverlayText(BuildContext context) => L10().barcodeScanAssign;
@override
Future<void> onBarcodeMatched(BuildContext context, Map<String, dynamic> data) async {
failureTone();
// If the barcode is known, we can"t assign it to the stock item!
showSnackIcon(
L10().barcodeInUse,
icon: FontAwesomeIcons.qrcode,
success: false
);
}
@override
Future<void> onBarcodeUnknown(BuildContext context, Map<String, dynamic> data) async {
// If the barcode is unknown, we *can* assign it to the stock item!
if (!data.containsKey("hash")) {
showServerError(
L10().missingData,
L10().barcodeMissingHash,
);
} else {
String hash = (data["hash"] ?? "") as String;
if (hash.isEmpty) {
failureTone();
showSnackIcon(
L10().barcodeError,
success: false,
);
} else {
// Close the barcode scanner
Navigator.of(context).pop();
callback(hash);
}
}
}
}
class InvenTreeQRView extends StatefulWidget { class InvenTreeQRView extends StatefulWidget {
const InvenTreeQRView(this._handler, {Key? key}) : super(key: key); const InvenTreeQRView(this._handler, {Key? key}) : super(key: key);

@ -1 +1 @@
Subproject commit 74d796f7f1174fc27d5c031e18f4adbe1e16e6a4 Subproject commit 5f30fef900ea027cd7fe90b2d87a6f02ced315c0

View File

@ -195,6 +195,13 @@ class _PurchaseOrderDetailState extends RefreshableState<PurchaseOrderDetailWidg
"nested": true, "nested": true,
}, },
"location": { "location": {
},
"barcode": {
"parent": "items",
"nested": true,
"type": "barcode",
"label": L10().barcodeAssign,
"required": false,
} }
}; };