2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-27 21:16:48 +00:00
inventree-app/lib/widget/fields.dart
Oliver e9eb84eace
Stock display (#379)
* Display stock quantity more prominently

* Cleanup search widget

* Update for stock_detail widget

* More tweaks

* Change bottom bar icon

* Display boolean parameters appropriately

* Adds ability to edit part parameters

* Bump icon size a bit

* Improvements to filter options

- Allow filtering by "option" type
- To start with, filter stock by status code

* Remove debug message

* Remove getTriState method

- No longer needed
- Remove associated unit tests

* Adjust filters based on server API version

* Muted colors
2023-06-24 11:34:42 +10:00

221 lines
5.3 KiB
Dart

import "dart:async";
import "dart:io";
import "package:file_picker/file_picker.dart";
import "package:flutter/material.dart";
import "package:font_awesome_flutter/font_awesome_flutter.dart";
import "package:image_picker/image_picker.dart";
import "package:one_context/one_context.dart";
import "package:inventree/l10.dart";
class FilePickerDialog {
static Future<File?> pickImageFromCamera() async {
final picker = ImagePicker();
final pickedImage = await picker.pickImage(source: ImageSource.camera);
if (pickedImage != null) {
return File(pickedImage.path);
}
return null;
}
static Future<File?> pickImageFromGallery() async {
final picker = ImagePicker();
final pickedImage = await picker.pickImage(source: ImageSource.gallery);
if (pickedImage != null) {
return File(pickedImage.path);
}
return null;
}
static Future<File?> pickFileFromDevice() async {
final FilePickerResult? result = await FilePicker.platform.pickFiles();
if (result != null) {
String? path = result.files.single.path;
if (path != null) {
return File(path);
}
}
return null;
}
// Present a dialog to pick a file, either from local file system or from camera
static Future<void> pickFile({String message = "", bool allowImages = true, bool allowFiles = true, Function(File)? onPicked}) async {
String title = "";
if (allowImages && !allowFiles) {
title = L10().selectImage;
} else {
title = L10().selectFile;
}
// Construct actions
List<Widget> actions = [
];
if (message.isNotEmpty) {
actions.add(
ListTile(
title: Text(message)
)
);
}
actions.add(
SimpleDialogOption(
child: ListTile(
leading: FaIcon(FontAwesomeIcons.fileArrowUp),
title: Text(allowFiles ? L10().selectFile : L10().selectImage),
),
onPressed: () async {
// Close the dialog
OneContext().popDialog();
File? file;
if (allowFiles) {
file = await pickFileFromDevice();
} else {
file = await pickImageFromGallery();
}
if (file != null) {
if (onPicked != null) {
onPicked(file);
}
}
},
)
);
if (allowImages) {
actions.add(
SimpleDialogOption(
child: ListTile(
leading: FaIcon(FontAwesomeIcons.camera),
title: Text(L10().takePicture),
),
onPressed: () async {
// Close the dialog
OneContext().popDialog();
File? file = await pickImageFromCamera();
if (file != null) {
if (onPicked != null) {
onPicked(file);
}
}
}
)
);
}
OneContext().showDialog(
builder: (context) {
return SimpleDialog(
title: Text(title),
children: actions,
);
}
);
}
}
class CheckBoxField extends FormField<bool> {
CheckBoxField({
String? label,
bool? initial = false,
bool tristate = false,
Function(bool?)? onSaved,
TextStyle? labelStyle,
String? helperText,
TextStyle? helperStyle,
}) :
super(
onSaved: onSaved,
initialValue: initial,
builder: (FormFieldState<bool> state) {
return CheckboxListTile(
title: label != null ? Text(label, style: labelStyle) : null,
value: state.value,
tristate: tristate,
onChanged: state.didChange,
subtitle: helperText != null ? Text(helperText, style: helperStyle) : null,
contentPadding: EdgeInsets.zero,
);
}
);
}
class StringField extends TextFormField {
StringField({String label = "", String? hint, String? initial, Function(String?)? onSaved, Function(String?)? validator, bool allowEmpty = false, bool isEnabled = true}) :
super(
decoration: InputDecoration(
labelText: allowEmpty ? label : label + "*",
hintText: hint
),
initialValue: initial,
onSaved: onSaved,
enabled: isEnabled,
validator: (value) {
if (!allowEmpty && value != null && value.isEmpty) {
return L10().valueCannotBeEmpty;
}
if (validator != null) {
return validator(value) as String?;
}
return null;
}
);
}
/*
* Helper class for quantity values
*/
class QuantityField extends TextFormField {
QuantityField({String label = "", String hint = "", double? max, TextEditingController? controller}) :
super(
decoration: InputDecoration(
labelText: label,
hintText: hint,
),
controller: controller,
keyboardType: TextInputType.numberWithOptions(signed: false, decimal: true),
validator: (value) {
if (value != null && value.isEmpty) return L10().quantityEmpty;
double quantity = double.tryParse(value.toString()) ?? 0;
if (quantity <= 0) return L10().quantityPositive;
if ((max != null) && (quantity > max)) return "Quantity must not exceed ${max}";
return null;
},
);
}