mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-29 20:40:35 +00:00 
			
		
		
		
	Adds "barcode" field handler for API forms
This commit is contained in:
		| @@ -7,6 +7,7 @@ import "package:date_field/date_field.dart"; | ||||
|  | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/app_colors.dart"; | ||||
| import 'package:inventree/barcode.dart'; | ||||
| import "package:inventree/helpers.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:inventree/inventree/sentry.dart"; | ||||
| @@ -269,7 +270,7 @@ class APIFormField { | ||||
|   } | ||||
|  | ||||
|   // Construct a widget for this input | ||||
|   Widget constructField() { | ||||
|   Widget constructField(BuildContext context) { | ||||
|     switch (type) { | ||||
|       case "string": | ||||
|       case "url": | ||||
| @@ -288,6 +289,8 @@ class APIFormField { | ||||
|         return _constructFileField(); | ||||
|       case "date": | ||||
|         return _constructDateField(); | ||||
|       case "barcode": | ||||
|         return _constructBarcodeField(context); | ||||
|       default: | ||||
|         return ListTile( | ||||
|           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 | ||||
|   Widget _constructDateField() { | ||||
|  | ||||
| @@ -937,7 +986,7 @@ class _APIFormWidgetState extends State<APIFormWidget> { | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       widgets.add(field.constructField()); | ||||
|       widgets.add(field.constructField(context)); | ||||
|  | ||||
|       if (field.hasErrors()) { | ||||
|         for (String error in field.errorMessages()) { | ||||
|   | ||||
| @@ -305,7 +305,7 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler { | ||||
|           } | ||||
|         ).then((result) { | ||||
|           if (result) { | ||||
|             failureTone(); | ||||
|             successTone(); | ||||
|  | ||||
|             Navigator.of(context).pop(); | ||||
|  | ||||
| @@ -315,7 +315,7 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler { | ||||
|                 icon: FontAwesomeIcons.qrcode | ||||
|             ); | ||||
|           } else { | ||||
|             successTone(); | ||||
|             failureTone(); | ||||
|  | ||||
|             showSnackIcon( | ||||
|                 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 { | ||||
|  | ||||
|   const InvenTreeQRView(this._handler, {Key? key}) : super(key: key); | ||||
|   | ||||
							
								
								
									
										2
									
								
								lib/l10n
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								lib/l10n
									
									
									
									
									
								
							 Submodule lib/l10n updated: 74d796f7f1...5f30fef900
									
								
							| @@ -195,6 +195,13 @@ class _PurchaseOrderDetailState extends RefreshableState<PurchaseOrderDetailWidg | ||||
|         "nested": true, | ||||
|       }, | ||||
|       "location": { | ||||
|       }, | ||||
|       "barcode": { | ||||
|         "parent": "items", | ||||
|         "nested": true, | ||||
|         "type": "barcode", | ||||
|         "label": L10().barcodeAssign, | ||||
|         "required": false, | ||||
|       } | ||||
|     }; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user