add carton editor for mix carton
This commit is contained in:
@@ -322,6 +322,8 @@
|
|||||||
"box.standard_carton_size":"Standard carton size",
|
"box.standard_carton_size":"Standard carton size",
|
||||||
"box.custom_size":"Custom size",
|
"box.custom_size":"Custom size",
|
||||||
"box.package_size":"Package",
|
"box.package_size":"Package",
|
||||||
|
"box.select.cartion":"Select cartons",
|
||||||
|
"box.no_carton":"There is no cartons in this shipment.",
|
||||||
"Boxes End ================================================================":"",
|
"Boxes End ================================================================":"",
|
||||||
|
|
||||||
"Delivery Start ================================================================":"",
|
"Delivery Start ================================================================":"",
|
||||||
|
|||||||
@@ -321,6 +321,8 @@
|
|||||||
"box.standard_carton_size":"Standard carton size",
|
"box.standard_carton_size":"Standard carton size",
|
||||||
"box.custom_size":"Custom size",
|
"box.custom_size":"Custom size",
|
||||||
"box.package_size":"Package",
|
"box.package_size":"Package",
|
||||||
|
"box.select.cartion":"Select cartons",
|
||||||
|
"box.no_carton":"There is no cartons in this shipment.",
|
||||||
"Boxes End ================================================================":"",
|
"Boxes End ================================================================":"",
|
||||||
|
|
||||||
"Delivery Start ================================================================":"",
|
"Delivery Start ================================================================":"",
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import 'pages/carton/model/carton_selection_model.dart';
|
||||||
import 'pages/delivery/model/delivery_model.dart';
|
import 'pages/delivery/model/delivery_model.dart';
|
||||||
|
|
||||||
class App extends StatefulWidget {
|
class App extends StatefulWidget {
|
||||||
@@ -62,6 +63,7 @@ class _AppState extends State<App> {
|
|||||||
final CartonSizeModel cartonSizeModel = new CartonSizeModel();
|
final CartonSizeModel cartonSizeModel = new CartonSizeModel();
|
||||||
final ProcessingModel processingModel = new ProcessingModel();
|
final ProcessingModel processingModel = new ProcessingModel();
|
||||||
final PickupModel pickupModel = new PickupModel();
|
final PickupModel pickupModel = new PickupModel();
|
||||||
|
final CartonSelectionModel cartonSelectionModel = new CartonSelectionModel();
|
||||||
|
|
||||||
late AppTranslationsDelegate _newLocaleDelegate;
|
late AppTranslationsDelegate _newLocaleDelegate;
|
||||||
|
|
||||||
@@ -84,7 +86,8 @@ class _AppState extends State<App> {
|
|||||||
..addModel(deliveryModel)
|
..addModel(deliveryModel)
|
||||||
..addModel(cartonSizeModel)
|
..addModel(cartonSizeModel)
|
||||||
..addModel(processingModel)
|
..addModel(processingModel)
|
||||||
..addModel(pickupModel);
|
..addModel(pickupModel)
|
||||||
|
..addModel(cartonSelectionModel);
|
||||||
|
|
||||||
_newLocaleDelegate = AppTranslationsDelegate(
|
_newLocaleDelegate = AppTranslationsDelegate(
|
||||||
newLocale: Translation().supportedLocales().first);
|
newLocale: Translation().supportedLocales().first);
|
||||||
@@ -133,6 +136,7 @@ class _AppState extends State<App> {
|
|||||||
ChangeNotifierProvider.value(value: cartonSizeModel),
|
ChangeNotifierProvider.value(value: cartonSizeModel),
|
||||||
ChangeNotifierProvider.value(value: processingModel),
|
ChangeNotifierProvider.value(value: processingModel),
|
||||||
ChangeNotifierProvider.value(value: pickupModel),
|
ChangeNotifierProvider.value(value: pickupModel),
|
||||||
|
ChangeNotifierProvider.value(value: cartonSelectionModel),
|
||||||
],
|
],
|
||||||
child: Consumer<LanguageModel>(
|
child: Consumer<LanguageModel>(
|
||||||
builder: (context, value, child) {
|
builder: (context, value, child) {
|
||||||
|
|||||||
@@ -95,6 +95,11 @@ const carton_from_shipments = "From shipments";
|
|||||||
const carton_small_bag = "Small bag";
|
const carton_small_bag = "Small bag";
|
||||||
const carton_mix_box = "Mix box";
|
const carton_mix_box = "Mix box";
|
||||||
|
|
||||||
|
// carton Size
|
||||||
|
const standardCarton = "Standard carton size";
|
||||||
|
const customCarton = "Custom size";
|
||||||
|
const packageCartion = "Package";
|
||||||
|
|
||||||
//Mix types
|
//Mix types
|
||||||
const mix_delivery = "Mix Delivery";
|
const mix_delivery = "Mix Delivery";
|
||||||
const mix_pickup = "Mix Pickup";
|
const mix_pickup = "Mix Pickup";
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class Carton {
|
|||||||
String? cartonSizeID;
|
String? cartonSizeID;
|
||||||
String? cartonSizeName;
|
String? cartonSizeName;
|
||||||
double cartonWeight;
|
double cartonWeight;
|
||||||
|
bool isSelected;
|
||||||
|
|
||||||
int rate;
|
int rate;
|
||||||
int weight;
|
int weight;
|
||||||
@@ -158,7 +159,8 @@ class Carton {
|
|||||||
this.mixBoxType,
|
this.mixBoxType,
|
||||||
this.mixCartons = const [],
|
this.mixCartons = const [],
|
||||||
this.mixCartonIDs = const [],
|
this.mixCartonIDs = const [],
|
||||||
this.cartonWeight =0});
|
this.cartonWeight =0,
|
||||||
|
this.isSelected = false});
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList();
|
List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList();
|
||||||
|
|||||||
@@ -80,4 +80,10 @@ class FcsShipment {
|
|||||||
fcsShipment.port != this.port ||
|
fcsShipment.port != this.port ||
|
||||||
fcsShipment.destination != this.destination;
|
fcsShipment.destination != this.destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => other is FcsShipment && other.id == id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => id.hashCode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:fcs/pages/user_search/user_serach.dart';
|
|||||||
import 'package:fcs/pages/widgets/display_text.dart';
|
import 'package:fcs/pages/widgets/display_text.dart';
|
||||||
import 'package:fcs/pages/widgets/fcs_id_icon.dart';
|
import 'package:fcs/pages/widgets/fcs_id_icon.dart';
|
||||||
import 'package:fcs/pages/widgets/local_app_bar.dart';
|
import 'package:fcs/pages/widgets/local_app_bar.dart';
|
||||||
|
import 'package:fcs/pages/widgets/local_radio.dart';
|
||||||
import 'package:fcs/pages/widgets/local_radio_buttons.dart';
|
import 'package:fcs/pages/widgets/local_radio_buttons.dart';
|
||||||
import 'package:fcs/pages/widgets/local_text.dart';
|
import 'package:fcs/pages/widgets/local_text.dart';
|
||||||
import 'package:fcs/pages/widgets/local_title.dart';
|
import 'package:fcs/pages/widgets/local_title.dart';
|
||||||
@@ -124,11 +125,10 @@ class _CartonEditorState extends State<CartonEditor> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
//for packages
|
//for packages
|
||||||
if (isFromPackages) {
|
if (isFromPackages) {
|
||||||
|
|
||||||
}
|
}
|
||||||
// for mix cartion
|
// for mix cartion
|
||||||
else {
|
else {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
CupertinoPageRoute(
|
CupertinoPageRoute(
|
||||||
builder: (context) => const MixCartonEditor()));
|
builder: (context) => const MixCartonEditor()));
|
||||||
@@ -244,14 +244,10 @@ class _CartonEditorState extends State<CartonEditor> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Row(children: <Widget>[
|
child: Row(children: <Widget>[
|
||||||
Radio(
|
LocalRadio(
|
||||||
visualDensity: const VisualDensity(
|
|
||||||
horizontal: VisualDensity.minimumDensity),
|
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
||||||
activeColor: primaryColor,
|
|
||||||
groupValue: _billToValue,
|
|
||||||
value: 1,
|
value: 1,
|
||||||
onChanged: (value) {
|
groupValue: _billToValue,
|
||||||
|
onChanged: (p0) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_billToValue = 1;
|
_billToValue = 1;
|
||||||
});
|
});
|
||||||
@@ -261,7 +257,7 @@ class _CartonEditorState extends State<CartonEditor> {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 10),
|
padding: const EdgeInsets.only(left: 10),
|
||||||
child: LocalText(context, 'box.bill_to_sender',
|
child: LocalText(context, 'box.bill_to_sender',
|
||||||
fontSize: 14,
|
fontSize: 15,
|
||||||
color: _billToValue == 1 ? primaryColor : Colors.black),
|
color: _billToValue == 1 ? primaryColor : Colors.black),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -275,14 +271,10 @@ class _CartonEditorState extends State<CartonEditor> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Row(children: <Widget>[
|
child: Row(children: <Widget>[
|
||||||
Radio(
|
LocalRadio(
|
||||||
visualDensity: const VisualDensity(
|
|
||||||
horizontal: VisualDensity.minimumDensity),
|
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
||||||
activeColor: primaryColor,
|
|
||||||
groupValue: _billToValue,
|
|
||||||
value: 2,
|
value: 2,
|
||||||
onChanged: (value) {
|
groupValue: _billToValue,
|
||||||
|
onChanged: (p0) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_billToValue = 2;
|
_billToValue = 2;
|
||||||
});
|
});
|
||||||
@@ -292,7 +284,7 @@ class _CartonEditorState extends State<CartonEditor> {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 10),
|
padding: const EdgeInsets.only(left: 10),
|
||||||
child: LocalText(context, 'box.bill_to.consignee',
|
child: LocalText(context, 'box.bill_to.consignee',
|
||||||
fontSize: 14,
|
fontSize: 15,
|
||||||
color: _billToValue == 2 ? primaryColor : Colors.black),
|
color: _billToValue == 2 ? primaryColor : Colors.black),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -327,7 +319,9 @@ class _CartonEditorState extends State<CartonEditor> {
|
|||||||
Flexible(child: consigneeBox)
|
Flexible(child: consigneeBox)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
billRadioBox
|
const SizedBox(height: 5),
|
||||||
|
billRadioBox,
|
||||||
|
const SizedBox(height: 5),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: Container(),
|
: Container(),
|
||||||
|
|||||||
116
lib/pages/carton/mix_cation/carton_selection_result.dart
Normal file
116
lib/pages/carton/mix_cation/carton_selection_result.dart
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
import 'package:fcs/pages/widgets/local_text.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../../domain/entities/carton.dart';
|
||||||
|
import '../../../helpers/theme.dart';
|
||||||
|
import '../model/carton_selection_model.dart';
|
||||||
|
|
||||||
|
typedef OnAction = Future<void> Function();
|
||||||
|
|
||||||
|
class CartonSelectionResult extends StatelessWidget {
|
||||||
|
final bool isLoadingMore;
|
||||||
|
final OnAction onLoadMore;
|
||||||
|
final OnAction onRefresh;
|
||||||
|
final Function(Carton)? onTap;
|
||||||
|
final ScrollController controller;
|
||||||
|
|
||||||
|
const CartonSelectionResult(
|
||||||
|
{super.key,
|
||||||
|
required this.isLoadingMore,
|
||||||
|
required this.onLoadMore,
|
||||||
|
required this.onRefresh,
|
||||||
|
this.onTap,
|
||||||
|
required this.controller});
|
||||||
|
|
||||||
|
bool _scrollNotification(ScrollNotification scrollInfo) {
|
||||||
|
if (!isLoadingMore &&
|
||||||
|
scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) {
|
||||||
|
onLoadMore();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var model = context.watch<CartonSelectionModel>();
|
||||||
|
List<Carton> searchResults = model.cartons;
|
||||||
|
|
||||||
|
return searchResults.isEmpty
|
||||||
|
? Center(
|
||||||
|
child: LocalText(context, 'box.no_carton',
|
||||||
|
color: Colors.black, fontSize: 15))
|
||||||
|
: Column(children: [
|
||||||
|
Expanded(
|
||||||
|
child: NotificationListener<ScrollNotification>(
|
||||||
|
onNotification: _scrollNotification,
|
||||||
|
child: RefreshIndicator(
|
||||||
|
color: primaryColor,
|
||||||
|
onRefresh: () => onRefresh(),
|
||||||
|
child: ListView.builder(
|
||||||
|
controller: controller,
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
Carton carton = searchResults[index];
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 5, bottom: 5),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
if (onTap != null) {
|
||||||
|
onTap!(carton);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.all(Radius.circular(5)),
|
||||||
|
border:
|
||||||
|
Border.all(color: Colors.grey.shade300)),
|
||||||
|
padding: EdgeInsets.only(left: 10, right: 10),
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: new Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 8.0),
|
||||||
|
child: new Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
new Text(carton.cartonNumber ?? "",
|
||||||
|
style: new TextStyle(
|
||||||
|
fontSize: 15.0,
|
||||||
|
color: Colors.black)),
|
||||||
|
new Text(
|
||||||
|
"${carton.cartonWeight.toStringAsFixed(2)} lb",
|
||||||
|
style: new TextStyle(
|
||||||
|
fontSize: 15.0,
|
||||||
|
color: Colors.grey),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
carton.isSelected
|
||||||
|
? Icon(Icons.check, color: primaryColor)
|
||||||
|
: const SizedBox()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
itemCount: searchResults.length)),
|
||||||
|
)),
|
||||||
|
Container(
|
||||||
|
height: isLoadingMore ? 50.0 : 0,
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: const Center(
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
valueColor: AlwaysStoppedAnimation<Color>(primaryColor)),
|
||||||
|
)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
246
lib/pages/carton/mix_cation/carton_selection_widget.dart
Normal file
246
lib/pages/carton/mix_cation/carton_selection_widget.dart
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
import 'package:fcs/domain/entities/fcs_shipment.dart';
|
||||||
|
import 'package:fcs/helpers/theme.dart';
|
||||||
|
import 'package:fcs/pages/carton/mix_cation/carton_selection_result.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../../domain/entities/carton.dart';
|
||||||
|
import '../../main/util.dart';
|
||||||
|
import '../../widgets/barcode_scanner.dart';
|
||||||
|
import '../../widgets/continue_button.dart';
|
||||||
|
import '../../widgets/local_title.dart';
|
||||||
|
import '../../widgets/previous_button.dart';
|
||||||
|
import '../model/carton_selection_model.dart';
|
||||||
|
|
||||||
|
typedef OnPrevious = Function(List<Carton> cartons);
|
||||||
|
typedef OnContinue = Function(List<Carton> cartons);
|
||||||
|
|
||||||
|
class CartonSelectionWidget extends StatefulWidget {
|
||||||
|
final FcsShipment shipment;
|
||||||
|
final List<Carton> cartons;
|
||||||
|
|
||||||
|
final OnPrevious? onPrevious;
|
||||||
|
final OnContinue? onContinue;
|
||||||
|
|
||||||
|
const CartonSelectionWidget({
|
||||||
|
Key? key,
|
||||||
|
required this.cartons,
|
||||||
|
this.onPrevious,
|
||||||
|
this.onContinue,
|
||||||
|
required this.shipment,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CartonSelectionWidget> createState() => _CartonSelectionWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CartonSelectionWidgetState extends State<CartonSelectionWidget> {
|
||||||
|
final TextEditingController _controller = TextEditingController();
|
||||||
|
String _query = "";
|
||||||
|
bool _isLoadMore = false;
|
||||||
|
final _scrollController = ScrollController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_init();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
_init() {
|
||||||
|
var searchModel = context.read<CartonSelectionModel>();
|
||||||
|
searchModel.addDefaultCartons(widget.shipment.id!);
|
||||||
|
|
||||||
|
_controller.text = searchModel.query;
|
||||||
|
_query = searchModel.query;
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant CartonSelectionWidget oldWidget) {
|
||||||
|
_init();
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _loadMoreData() async {
|
||||||
|
if (_isLoadMore) return;
|
||||||
|
var model = context.read<CartonSelectionModel>();
|
||||||
|
if (model.reachEnd || model.ended) return;
|
||||||
|
setState(() {
|
||||||
|
_isLoadMore = true;
|
||||||
|
});
|
||||||
|
if (_query != "") {
|
||||||
|
await model.loadMoreSearch(term: _query, shipmentId: widget.shipment.id!);
|
||||||
|
} else {
|
||||||
|
await model.loadMoreData(widget.shipment.id!);
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_isLoadMore = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var model = context.watch<CartonSelectionModel>();
|
||||||
|
List<Carton> searchResults = model.cartons;
|
||||||
|
List<Carton> selectedCartonList = model.selectedCartonList;
|
||||||
|
|
||||||
|
final continueBtn = ContinueButton(
|
||||||
|
onTap: () {
|
||||||
|
|
||||||
|
if (selectedCartonList.isEmpty || searchResults.isEmpty) {
|
||||||
|
showMsgDialog(context, 'Error', "Please select the cartons");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget.onContinue != null) {
|
||||||
|
widget.onContinue!(selectedCartonList);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final previousBtn = PreviousButton(onTap: () {
|
||||||
|
if (widget.onPrevious != null) {
|
||||||
|
widget.onPrevious!(selectedCartonList);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final searchBox = SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: TextField(
|
||||||
|
controller: _controller,
|
||||||
|
cursorColor: primaryColor,
|
||||||
|
onSubmitted: (value) {
|
||||||
|
setState(() {
|
||||||
|
_query = value;
|
||||||
|
});
|
||||||
|
_search(imm: true);
|
||||||
|
},
|
||||||
|
onChanged: (v) {
|
||||||
|
setState(() {
|
||||||
|
_query = v;
|
||||||
|
});
|
||||||
|
_search();
|
||||||
|
},
|
||||||
|
decoration: InputDecoration(
|
||||||
|
enabledBorder: const OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: labelColor),
|
||||||
|
),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: labelColor.withOpacity(0.3), width: 0)),
|
||||||
|
focusedBorder: const OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(5.0)),
|
||||||
|
borderSide: BorderSide(color: labelColor),
|
||||||
|
),
|
||||||
|
hintText: "Search by carton number",
|
||||||
|
hintStyle: const TextStyle(
|
||||||
|
color: Colors.grey,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.normal),
|
||||||
|
suffixIcon: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
InkResponse(
|
||||||
|
radius: 20,
|
||||||
|
onTap: () {
|
||||||
|
_scan(context);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.qr_code_scanner,
|
||||||
|
color: Colors.black87)),
|
||||||
|
IconButton(
|
||||||
|
splashRadius: 20,
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_controller.clear();
|
||||||
|
_query = "";
|
||||||
|
});
|
||||||
|
_search();
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.close, color: Colors.black87)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
contentPadding: const EdgeInsets.all(10),
|
||||||
|
filled: true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(left: 10, right: 10),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
LocalTitle(textKey: "box.select.cartion"),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
searchBox,
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 10),
|
||||||
|
child: CartonSelectionResult(
|
||||||
|
controller: _scrollController,
|
||||||
|
isLoadingMore: _isLoadMore,
|
||||||
|
onLoadMore: _loadMoreData,
|
||||||
|
onRefresh: () async {
|
||||||
|
_init();
|
||||||
|
},
|
||||||
|
onTap: (a) async {
|
||||||
|
setState(() {
|
||||||
|
a.isSelected = !a.isSelected;
|
||||||
|
});
|
||||||
|
context.read<CartonSelectionModel>().selectCarton(a);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
widget.onContinue != null
|
||||||
|
? Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 15, right: 15, top: 10),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
previousBtn,
|
||||||
|
continueBtn,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const SizedBox(),
|
||||||
|
const SizedBox(height: 20)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_scan(BuildContext context) async {
|
||||||
|
try {
|
||||||
|
String? barcode = await scanBarcode();
|
||||||
|
if (barcode != null) {
|
||||||
|
setState(() {
|
||||||
|
_controller.text = barcode;
|
||||||
|
_query = barcode;
|
||||||
|
});
|
||||||
|
await _search();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
showMsgDialog(context, 'Error', e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_search({bool imm = false}) async {
|
||||||
|
try {
|
||||||
|
await context
|
||||||
|
.read<CartonSelectionModel>()
|
||||||
|
.search(_query, imm: imm, shipmentId: widget.shipment.id!);
|
||||||
|
} catch (e) {
|
||||||
|
showMsgDialog(context, 'Error', e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,21 @@
|
|||||||
|
// ignore_for_file: deprecated_member_use
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../../domain/constants.dart';
|
||||||
|
import '../../../domain/entities/carton.dart';
|
||||||
|
import '../../../domain/entities/carton_size.dart';
|
||||||
|
import '../../../domain/entities/fcs_shipment.dart';
|
||||||
import '../../../domain/vo/local_step.dart';
|
import '../../../domain/vo/local_step.dart';
|
||||||
import '../../../helpers/theme.dart';
|
import '../../../helpers/theme.dart';
|
||||||
import '../../widgets/local_text.dart';
|
import '../../widgets/local_text.dart';
|
||||||
import '../../widgets/progress.dart';
|
import '../../widgets/progress.dart';
|
||||||
import '../../widgets/step_widget.dart';
|
import '../../widgets/step_widget.dart';
|
||||||
|
import '../model/carton_selection_model.dart';
|
||||||
|
import 'carton_selection_widget.dart';
|
||||||
import 'type_widget.dart';
|
import 'type_widget.dart';
|
||||||
|
|
||||||
class MixCartonEditor extends StatefulWidget {
|
class MixCartonEditor extends StatefulWidget {
|
||||||
@@ -26,12 +35,21 @@ class _MixCartonEditorState extends State<MixCartonEditor> {
|
|||||||
LocalStep(lable: 'Cartons', stepType: StepType.CARTONS),
|
LocalStep(lable: 'Cartons', stepType: StepType.CARTONS),
|
||||||
LocalStep(lable: 'Submit', stepType: StepType.SUBMIT)
|
LocalStep(lable: 'Submit', stepType: StepType.SUBMIT)
|
||||||
];
|
];
|
||||||
|
List<Carton> _cartions = [];
|
||||||
|
|
||||||
bool _isLoading = false;
|
|
||||||
int currentStep = 0;
|
int currentStep = 0;
|
||||||
|
double _length = 0;
|
||||||
|
double _width = 0;
|
||||||
|
double _height = 0;
|
||||||
|
|
||||||
|
FcsShipment? _shipment;
|
||||||
|
String _cartionSizeType = standardCarton;
|
||||||
|
CartonSize? _standardSize;
|
||||||
|
bool _isLoading = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
context.read<CartonSelectionModel>().clearSelection();
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,57 +116,48 @@ class _MixCartonEditorState extends State<MixCartonEditor> {
|
|||||||
Widget getContent(int index) {
|
Widget getContent(int index) {
|
||||||
var step = steps[index];
|
var step = steps[index];
|
||||||
if (step.stepType == StepType.TYPE) {
|
if (step.stepType == StepType.TYPE) {
|
||||||
return Expanded(child: TypeWidget(
|
return Expanded(
|
||||||
|
child: TypeWidget(
|
||||||
|
shipment: _shipment,
|
||||||
|
cartonSizeType: _cartionSizeType,
|
||||||
|
standardSize: _standardSize,
|
||||||
|
length: _length,
|
||||||
|
width: _width,
|
||||||
|
height: _height,
|
||||||
onPrevious: () {
|
onPrevious: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
// warehouse: _warehouse,
|
onContinue: (shipment, cartonSizeType,
|
||||||
// onSelectWarehouse: (w) {
|
{standardSize, length, width, height}) {
|
||||||
// setState(() {
|
setState(() {
|
||||||
// _warehouse = w;
|
_shipment = shipment;
|
||||||
// currentStep += 1;
|
_cartionSizeType = cartonSizeType;
|
||||||
// });
|
_standardSize = standardSize;
|
||||||
// },
|
_length = length ?? 0;
|
||||||
|
_width = width ?? 0;
|
||||||
|
_height = height ?? 0;
|
||||||
|
currentStep += 1;
|
||||||
|
});
|
||||||
|
},
|
||||||
));
|
));
|
||||||
} else if (step.stepType == StepType.CARTONS) {
|
} else if (step.stepType == StepType.CARTONS) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: Text("cartons"),
|
child: CartonSelectionWidget(
|
||||||
// child: StockAdjustmentProducts(
|
shipment: _shipment!,
|
||||||
// products: products,
|
cartons: _cartions,
|
||||||
// onAdd: (ps) {
|
onContinue: (cartons) {
|
||||||
// setState(() {
|
setState(() {
|
||||||
// products = List.from(ps);
|
_cartions = List.from(cartons);
|
||||||
// });
|
currentStep += 1;
|
||||||
// },
|
});
|
||||||
// onRemove: (p) {
|
},
|
||||||
// setState(() {
|
onPrevious: (cartons) {
|
||||||
// products.removeWhere((e) => e.id == p.id);
|
setState(() {
|
||||||
// });
|
_cartions = List.from(cartons);
|
||||||
// },
|
currentStep -= 1;
|
||||||
// onRemoveAll: (ps) {
|
});
|
||||||
// for (var e in ps) {
|
},
|
||||||
// setState(() {
|
),
|
||||||
// products.removeWhere((p) => p.id == e.id);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// onContinue: (ps) {
|
|
||||||
// if (products.isEmpty) {
|
|
||||||
// showMsgDialog(context, 'Error', "Please select product");
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// setState(() {
|
|
||||||
// products = List.from(ps);
|
|
||||||
// currentStep += 1;
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// onPrevious: (ps) {
|
|
||||||
// setState(() {
|
|
||||||
// products = List.from(ps);
|
|
||||||
// currentStep -= 1;
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
|
import 'package:fcs/pages/widgets/local_radio.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import '../../../domain/constants.dart';
|
||||||
|
import '../../../domain/entities/carton_size.dart';
|
||||||
import '../../../domain/entities/fcs_shipment.dart';
|
import '../../../domain/entities/fcs_shipment.dart';
|
||||||
import '../../../helpers/theme.dart';
|
import '../../../helpers/theme.dart';
|
||||||
|
import '../../carton_size/model/carton_size_model.dart';
|
||||||
import '../../fcs_shipment/model/fcs_shipment_model.dart';
|
import '../../fcs_shipment/model/fcs_shipment_model.dart';
|
||||||
import '../../main/util.dart';
|
import '../../main/util.dart';
|
||||||
|
import '../../widgets/box_size_picker.dart';
|
||||||
import '../../widgets/continue_button.dart';
|
import '../../widgets/continue_button.dart';
|
||||||
import '../../widgets/local_dropdown.dart';
|
import '../../widgets/local_dropdown.dart';
|
||||||
import '../../widgets/local_text.dart';
|
import '../../widgets/local_text.dart';
|
||||||
@@ -13,15 +18,29 @@ import '../../widgets/previous_button.dart';
|
|||||||
|
|
||||||
typedef OnPrevious = Function();
|
typedef OnPrevious = Function();
|
||||||
|
|
||||||
|
typedef OnContinue = Function(FcsShipment shipment, String cartonSizeType,
|
||||||
|
{CartonSize? standardSize, double? length, double? width, double? height});
|
||||||
|
|
||||||
class TypeWidget extends StatefulWidget {
|
class TypeWidget extends StatefulWidget {
|
||||||
final OnPrevious? onPrevious;
|
final OnPrevious? onPrevious;
|
||||||
final bool isTransferFrom;
|
final OnContinue? onContinue;
|
||||||
final bool isTransferTo;
|
final FcsShipment? shipment;
|
||||||
|
final String cartonSizeType;
|
||||||
|
final CartonSize? standardSize;
|
||||||
|
final double? length;
|
||||||
|
final double? width;
|
||||||
|
final double? height;
|
||||||
|
|
||||||
const TypeWidget(
|
const TypeWidget(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
this.onPrevious,
|
this.onPrevious,
|
||||||
this.isTransferFrom = false,
|
this.onContinue,
|
||||||
this.isTransferTo = false})
|
this.shipment,
|
||||||
|
required this.cartonSizeType,
|
||||||
|
this.standardSize,
|
||||||
|
this.length,
|
||||||
|
this.width,
|
||||||
|
this.height})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -30,14 +49,14 @@ class TypeWidget extends StatefulWidget {
|
|||||||
|
|
||||||
class _TypeWidgetState extends State<TypeWidget> {
|
class _TypeWidgetState extends State<TypeWidget> {
|
||||||
FcsShipment? _shipment;
|
FcsShipment? _shipment;
|
||||||
List<FcsShipment> shipments = [];
|
String _cartionSizeType = standardCarton;
|
||||||
List<String> standardSizeList = [
|
|
||||||
'Large - 20”x20”x20”',
|
List<FcsShipment> _shipments = [];
|
||||||
'Medium - 15”x15”x15”',
|
CartonSize? _selectStandardSize;
|
||||||
'Small - 10”x10”x10”'
|
|
||||||
];
|
TextEditingController _widthController = new TextEditingController();
|
||||||
int _cartinSizeValue = 1;
|
TextEditingController _heightController = new TextEditingController();
|
||||||
late String selectedValue;
|
TextEditingController _lengthController = new TextEditingController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -46,10 +65,22 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_init() async {
|
_init() async {
|
||||||
selectedValue = standardSizeList[1];
|
_shipment = widget.shipment;
|
||||||
|
_cartionSizeType = widget.cartonSizeType;
|
||||||
|
|
||||||
|
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
|
||||||
|
_selectStandardSize = widget.standardSize ?? cartonSizes.first;
|
||||||
|
|
||||||
|
_lengthController.text =
|
||||||
|
widget.length == null ? "0" : widget.length.toString();
|
||||||
|
_widthController.text =
|
||||||
|
widget.width == null ? "0" : widget.width.toString();
|
||||||
|
_heightController.text =
|
||||||
|
widget.height == null ? "0" : widget.height.toString();
|
||||||
|
|
||||||
var fcsShipments =
|
var fcsShipments =
|
||||||
await context.read<FcsShipmentModel>().getActiveFcsShipments();
|
await context.read<FcsShipmentModel>().getActiveFcsShipments();
|
||||||
shipments = fcsShipments;
|
_shipments = fcsShipments;
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
@@ -58,11 +89,42 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
List<CartonSize> cartonSizes = context.watch<CartonSizeModel>().cartonSizes;
|
||||||
|
bool isStandardSize = _cartionSizeType == standardCarton;
|
||||||
|
bool isCustomSize = _cartionSizeType == customCarton;
|
||||||
|
bool isNoneDefinedSize = _cartionSizeType == packageCartion;
|
||||||
|
|
||||||
final continueBtn = ContinueButton(onTap: () {
|
final continueBtn = ContinueButton(onTap: () {
|
||||||
|
double l = double.tryParse(_lengthController.text) ?? 0;
|
||||||
|
double w = double.tryParse(_widthController.text) ?? 0;
|
||||||
|
double h = double.tryParse(_heightController.text) ?? 0;
|
||||||
|
|
||||||
if (_shipment == null) {
|
if (_shipment == null) {
|
||||||
showMsgDialog(context, "Error", "Please select shipment");
|
showMsgDialog(context, "Error", "Please select shipment");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isStandardSize &&
|
||||||
|
_selectStandardSize == null &&
|
||||||
|
!isCustomSize &&
|
||||||
|
!isNoneDefinedSize) {
|
||||||
|
showMsgDialog(
|
||||||
|
context, "Error", "Please select the standard cartion size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCustomSize &&
|
||||||
|
!isStandardSize &&
|
||||||
|
!isNoneDefinedSize &&
|
||||||
|
(l == 0 || w == 0 || h == 0)) {
|
||||||
|
showMsgDialog(context, "Error", "Please add the cartion size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget.onContinue != null) {
|
||||||
|
widget.onContinue!(_shipment!, _cartionSizeType,
|
||||||
|
standardSize: _selectStandardSize, length: l, width: w, height: h);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
final previousBtn = PreviousButton(onTap: () {
|
final previousBtn = PreviousButton(onTap: () {
|
||||||
@@ -72,52 +134,83 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
final standardSizeBox = Padding(
|
final standardSizeBox = Padding(
|
||||||
padding: const EdgeInsets.only(left: 35.0),
|
padding: const EdgeInsets.only(left: 34.0, top: 8),
|
||||||
child: DropdownButton<String>(
|
child: IgnorePointer(
|
||||||
isDense: true,
|
ignoring: !isStandardSize,
|
||||||
value: selectedValue,
|
child: DropdownButton<CartonSize>(
|
||||||
style: TextStyle(color: Colors.black, fontSize: 14),
|
isDense: true,
|
||||||
underline: Container(
|
value: _selectStandardSize,
|
||||||
height: 1,
|
style: TextStyle(color: Colors.black, fontSize: 14),
|
||||||
color: Colors.grey,
|
underline: Container(height: 1, color: Colors.grey),
|
||||||
|
onChanged: (newValue) {
|
||||||
|
setState(() {
|
||||||
|
_selectStandardSize = newValue!;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
isExpanded: true,
|
||||||
|
items:
|
||||||
|
cartonSizes.map<DropdownMenuItem<CartonSize>>((CartonSize value) {
|
||||||
|
return DropdownMenuItem<CartonSize>(
|
||||||
|
value: value,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text("${value.name} - ",
|
||||||
|
style: TextStyle(
|
||||||
|
color: isStandardSize ? Colors.black : labelColor)),
|
||||||
|
Text(
|
||||||
|
"${value.length.toInt()}”x${value.width.toInt()}”x${value.height.toInt()}”",
|
||||||
|
style: TextStyle(color: labelColor)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
),
|
),
|
||||||
onChanged: (newValue) {
|
),
|
||||||
setState(() {
|
);
|
||||||
selectedValue = newValue!;
|
|
||||||
});
|
final lengthBox = BoxSizePicker(
|
||||||
},
|
lableKey: 'box.length',
|
||||||
isExpanded: true,
|
controller: _lengthController,
|
||||||
items: standardSizeList.map<DropdownMenuItem<String>>((String value) {
|
enable: isCustomSize);
|
||||||
return DropdownMenuItem<String>(
|
|
||||||
value: value,
|
final widthBox = BoxSizePicker(
|
||||||
child: Text(value.toString(),
|
lableKey: 'box.width',
|
||||||
overflow: TextOverflow.ellipsis,
|
controller: _widthController,
|
||||||
style: TextStyle(color: Colors.black)),
|
enable: isCustomSize);
|
||||||
);
|
|
||||||
}).toList(),
|
final heightBox = BoxSizePicker(
|
||||||
|
lableKey: 'box.height',
|
||||||
|
controller: _heightController,
|
||||||
|
enable: isCustomSize);
|
||||||
|
|
||||||
|
final customSizeBox = Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 34.0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Flexible(child: lengthBox),
|
||||||
|
Flexible(child: widthBox),
|
||||||
|
Flexible(child: heightBox)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final cartonSizedBox = Column(
|
final cartonSizedBox = Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
// standard carton size
|
// standard carton size
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_cartinSizeValue = 1;
|
_cartionSizeType = standardCarton;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Row(children: <Widget>[
|
child: Row(children: <Widget>[
|
||||||
Radio(
|
LocalRadio(
|
||||||
visualDensity:
|
value: standardCarton,
|
||||||
const VisualDensity(horizontal: VisualDensity.minimumDensity),
|
groupValue: _cartionSizeType,
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
onChanged: (p0) {
|
||||||
activeColor: primaryColor,
|
|
||||||
groupValue: _cartinSizeValue,
|
|
||||||
value: 1,
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_cartinSizeValue = 1;
|
_cartionSizeType = standardCarton;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -125,32 +218,28 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 10),
|
padding: const EdgeInsets.only(left: 10),
|
||||||
child: LocalText(context, 'box.standard_carton_size',
|
child: LocalText(context, 'box.standard_carton_size',
|
||||||
fontSize: 14,
|
fontSize: 15,
|
||||||
color: _cartinSizeValue == 1 ? primaryColor : Colors.black),
|
color: isStandardSize ? primaryColor : labelColor),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
standardSizeBox,
|
standardSizeBox,
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 20),
|
||||||
// custom size
|
// custom size
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_cartinSizeValue = 2;
|
_cartionSizeType = customCarton;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Row(children: <Widget>[
|
child: Row(children: <Widget>[
|
||||||
Radio(
|
LocalRadio(
|
||||||
visualDensity:
|
value: customCarton,
|
||||||
const VisualDensity(horizontal: VisualDensity.minimumDensity),
|
groupValue: _cartionSizeType,
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
onChanged: (p0) {
|
||||||
activeColor: primaryColor,
|
|
||||||
groupValue: _cartinSizeValue,
|
|
||||||
value: 2,
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_cartinSizeValue = 2;
|
_cartionSizeType = customCarton;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -158,30 +247,28 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 10),
|
padding: const EdgeInsets.only(left: 10),
|
||||||
child: LocalText(context, 'box.custom_size',
|
child: LocalText(context, 'box.custom_size',
|
||||||
fontSize: 14,
|
fontSize: 15,
|
||||||
color: _cartinSizeValue == 2 ? primaryColor : Colors.black),
|
color: isCustomSize ? primaryColor : Colors.black54),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
|
customSizeBox,
|
||||||
|
const SizedBox(height: 10),
|
||||||
// not defined size
|
// not defined size
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_cartinSizeValue = 3;
|
_cartionSizeType = packageCartion;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Row(children: <Widget>[
|
child: Row(children: <Widget>[
|
||||||
Radio(
|
LocalRadio(
|
||||||
visualDensity:
|
value: packageCartion,
|
||||||
const VisualDensity(horizontal: VisualDensity.minimumDensity),
|
groupValue: _cartionSizeType,
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
onChanged: (p0) {
|
||||||
activeColor: primaryColor,
|
|
||||||
groupValue: _cartinSizeValue,
|
|
||||||
value: 3,
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_cartinSizeValue = 3;
|
_cartionSizeType = packageCartion;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -189,12 +276,21 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 10),
|
padding: const EdgeInsets.only(left: 10),
|
||||||
child: LocalText(context, 'box.package_size',
|
child: LocalText(context, 'box.package_size',
|
||||||
fontSize: 14,
|
fontSize: 15,
|
||||||
color: _cartinSizeValue == 3 ? primaryColor : Colors.black),
|
color: isNoneDefinedSize ? primaryColor : Colors.black54),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 34.0),
|
||||||
|
child: Text(
|
||||||
|
"No defined size",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: isNoneDefinedSize ? Colors.black : labelColor),
|
||||||
|
),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -210,7 +306,7 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
iconData: Ionicons.ios_airplane,
|
iconData: Ionicons.ios_airplane,
|
||||||
display: (u) => u.shipmentNumber,
|
display: (u) => u.shipmentNumber,
|
||||||
selectedValue: _shipment,
|
selectedValue: _shipment,
|
||||||
values: shipments,
|
values: _shipments,
|
||||||
));
|
));
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
@@ -220,9 +316,13 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
child: ListView(
|
child: ListView(
|
||||||
padding: EdgeInsets.only(left: 10, right: 10),
|
padding: EdgeInsets.only(left: 10, right: 10),
|
||||||
children: [
|
children: [
|
||||||
|
const SizedBox(height: 8),
|
||||||
LocalTitle(textKey: "box.select_carton_size"),
|
LocalTitle(textKey: "box.select_carton_size"),
|
||||||
|
const SizedBox(height: 8),
|
||||||
cartonSizedBox,
|
cartonSizedBox,
|
||||||
|
const SizedBox(height: 8),
|
||||||
LocalTitle(textKey: "box.select_shipment"),
|
LocalTitle(textKey: "box.select_shipment"),
|
||||||
|
const SizedBox(height: 5),
|
||||||
fcsShipmentsBox
|
fcsShipmentsBox
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
|
|||||||
142
lib/pages/carton/model/carton_selection_model.dart
Normal file
142
lib/pages/carton/model/carton_selection_model.dart
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:fcs/domain/entities/carton.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
|
import '../../../domain/constants.dart';
|
||||||
|
import '../../main/model/base_model.dart';
|
||||||
|
|
||||||
|
class CartonSelectionModel extends BaseModel {
|
||||||
|
final log = Logger("CartonSelectionModel");
|
||||||
|
// for search
|
||||||
|
String query = "";
|
||||||
|
int offset = 0;
|
||||||
|
bool reachEnd = false;
|
||||||
|
List<Carton> cartons = [];
|
||||||
|
|
||||||
|
// for default carton
|
||||||
|
DocumentSnapshot? _lastDocument;
|
||||||
|
bool ended = false;
|
||||||
|
|
||||||
|
List<Carton> selectedCartonList = [];
|
||||||
|
|
||||||
|
Timer? t;
|
||||||
|
search(String term, {bool imm = false, required String shipmentId}) async {
|
||||||
|
query = term;
|
||||||
|
cartons.clear();
|
||||||
|
offset = 0;
|
||||||
|
reachEnd = false;
|
||||||
|
t?.cancel();
|
||||||
|
t = Timer(Duration(milliseconds: imm ? 0 : 800), () async {
|
||||||
|
await loadMoreSearch(term: term, shipmentId: shipmentId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> loadMoreSearch(
|
||||||
|
{required String term, required String shipmentId}) async {
|
||||||
|
if (term == "") {
|
||||||
|
await _refresh(shipmentId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// int rowPerPage = 21;
|
||||||
|
// List<Carton> list = [];
|
||||||
|
// SearchPara searchPara = SearchPara(filters: [], term: term);
|
||||||
|
// isLoading = true;
|
||||||
|
|
||||||
|
// var path =
|
||||||
|
// "/search/$cartons_collection/${searchPara.escapeTerm}/$rowPerPage/$offset/${searchPara.escapeFilters}";
|
||||||
|
|
||||||
|
// var result = await requestAPI(path, "GET",
|
||||||
|
// token: await getToken(), url: Config.instance.searchURL);
|
||||||
|
|
||||||
|
// if (result != null) {
|
||||||
|
// for (var row in result) {
|
||||||
|
// var item = ArtistExt.fromMapForSearch(row);
|
||||||
|
// list.add(item);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (var p in list) {
|
||||||
|
// selectedArtistList.contains(p)
|
||||||
|
// ? p.isSelected = true
|
||||||
|
// : p.isSelected = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// artists.addAll(list);
|
||||||
|
// offset += rowPerPage;
|
||||||
|
// if (list.length < rowPerPage) {
|
||||||
|
// reachEnd = true;
|
||||||
|
// }
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
addDefaultCartons(String shipmentId) async {
|
||||||
|
cartons.clear();
|
||||||
|
await _refresh(shipmentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectCarton(Carton a) {
|
||||||
|
if (a.isSelected) {
|
||||||
|
selectedCartonList.add(a);
|
||||||
|
} else {
|
||||||
|
selectedCartonList.remove(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _refresh(String shipmentId) async {
|
||||||
|
cartons.clear();
|
||||||
|
_lastDocument = null;
|
||||||
|
ended = false;
|
||||||
|
await loadMoreData(shipmentId);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> loadMoreData(String shipmentId) async {
|
||||||
|
int rowPerPage = 20;
|
||||||
|
|
||||||
|
try {
|
||||||
|
String path = "/$cartons_collection";
|
||||||
|
Query query = FirebaseFirestore.instance
|
||||||
|
.collection(path)
|
||||||
|
.where("fcs_shipment_id", isEqualTo: shipmentId)
|
||||||
|
// .where("status", isEqualTo: carton_processing_status)
|
||||||
|
// .where("carton_type", isEqualTo: carton_mix_box)
|
||||||
|
.where("is_deleted", isEqualTo: false)
|
||||||
|
.orderBy("created_at", descending: true);
|
||||||
|
|
||||||
|
if (_lastDocument != null) {
|
||||||
|
query = query.startAfterDocument(_lastDocument!);
|
||||||
|
}
|
||||||
|
|
||||||
|
QuerySnapshot querySnap = await query.limit(rowPerPage).get();
|
||||||
|
|
||||||
|
if (querySnap.docs.isEmpty) return;
|
||||||
|
_lastDocument = querySnap.docs[querySnap.docs.length - 1];
|
||||||
|
|
||||||
|
List<Carton> list = querySnap.docs.map((documentSnapshot) {
|
||||||
|
var p = Carton.fromMap(documentSnapshot.data() as Map<String, dynamic>,
|
||||||
|
documentSnapshot.id);
|
||||||
|
return p;
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
for (var p in list) {
|
||||||
|
selectedCartonList.contains(p)
|
||||||
|
? p.isSelected = true
|
||||||
|
: p.isSelected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cartons.addAll(list);
|
||||||
|
if (list.length < rowPerPage) ended = true;
|
||||||
|
notifyListeners();
|
||||||
|
} catch (e) {
|
||||||
|
log.warning("error:$e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearSelection() {
|
||||||
|
selectedCartonList.clear();
|
||||||
|
cartons.clear();
|
||||||
|
query = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
47
lib/pages/widgets/box_size_picker.dart
Normal file
47
lib/pages/widgets/box_size_picker.dart
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../helpers/theme.dart';
|
||||||
|
import 'input_text.dart';
|
||||||
|
import 'local_text.dart';
|
||||||
|
|
||||||
|
class BoxSizePicker extends StatelessWidget {
|
||||||
|
final TextEditingController? controller;
|
||||||
|
final String lableKey;
|
||||||
|
final bool enable;
|
||||||
|
const BoxSizePicker(
|
||||||
|
{super.key, this.controller, required this.lableKey, this.enable = true});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 4),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
LocalText(context, lableKey,
|
||||||
|
color: enable ? Colors.black : labelColor, fontSize: 15),
|
||||||
|
Text("inches",
|
||||||
|
style: TextStyle(color: labelColor, fontSize: 12))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: InputText(
|
||||||
|
isDense: true,
|
||||||
|
enabled: enable,
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
controller: controller,
|
||||||
|
withBorder: true,
|
||||||
|
textInputType: TextInputType.number,
|
||||||
|
constraints: BoxConstraints(maxWidth: 50, maxHeight: 40),
|
||||||
|
contentPadding: EdgeInsets.all(7),
|
||||||
|
borderColor: enable ? primaryColor : labelColor))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,10 +28,9 @@ class DisplayText extends StatelessWidget {
|
|||||||
var languageModel = Provider.of<LanguageModel>(context);
|
var languageModel = Provider.of<LanguageModel>(context);
|
||||||
|
|
||||||
var labelStyle = languageModel.isEng
|
var labelStyle = languageModel.isEng
|
||||||
? TextStyle(
|
? TextStyle(color: Colors.black54, fontSize: 15)
|
||||||
color: Colors.black54,
|
: TextStyle(
|
||||||
)
|
color: Colors.black54, fontFamily: "Myanmar3", fontSize: 15);
|
||||||
: TextStyle(color: Colors.black54, fontFamily: "Myanmar3");
|
|
||||||
var textStyle = languageModel.isEng
|
var textStyle = languageModel.isEng
|
||||||
? TextStyle(color: Colors.black)
|
? TextStyle(color: Colors.black)
|
||||||
: TextStyle(color: Colors.black, fontFamily: "Myanmar3");
|
: TextStyle(color: Colors.black, fontFamily: "Myanmar3");
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ class InputText extends StatelessWidget {
|
|||||||
final bool autoFocus;
|
final bool autoFocus;
|
||||||
final TextAlign textAlign;
|
final TextAlign textAlign;
|
||||||
final bool enabled;
|
final bool enabled;
|
||||||
|
final BoxConstraints? constraints;
|
||||||
|
final EdgeInsetsGeometry? contentPadding;
|
||||||
|
final bool? isDense;
|
||||||
|
|
||||||
const InputText(
|
const InputText(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
@@ -29,7 +32,10 @@ class InputText extends StatelessWidget {
|
|||||||
this.autoFocus = false,
|
this.autoFocus = false,
|
||||||
this.textInputType,
|
this.textInputType,
|
||||||
this.enabled = true,
|
this.enabled = true,
|
||||||
this.textAlign = TextAlign.start})
|
this.textAlign = TextAlign.start,
|
||||||
|
this.constraints,
|
||||||
|
this.contentPadding,
|
||||||
|
this.isDense})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -47,6 +53,9 @@ class InputText extends StatelessWidget {
|
|||||||
keyboardType: textInputType,
|
keyboardType: textInputType,
|
||||||
textAlign: textAlign,
|
textAlign: textAlign,
|
||||||
decoration: new InputDecoration(
|
decoration: new InputDecoration(
|
||||||
|
isDense: isDense,
|
||||||
|
constraints: constraints,
|
||||||
|
contentPadding: contentPadding,
|
||||||
// hintText: '',
|
// hintText: '',
|
||||||
hintStyle: TextStyle(
|
hintStyle: TextStyle(
|
||||||
height: 1.5,
|
height: 1.5,
|
||||||
@@ -65,16 +74,28 @@ class InputText extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
enabledBorder: withBorder
|
enabledBorder: withBorder
|
||||||
? OutlineInputBorder(
|
? OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: primaryColor, width: 1.0),
|
borderSide: BorderSide(
|
||||||
|
color: borderColor ?? primaryColor, width: 1.0),
|
||||||
)
|
)
|
||||||
: UnderlineInputBorder(
|
: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(color: primaryColor, width: 1.0)),
|
borderSide: BorderSide(
|
||||||
|
color: borderColor ?? primaryColor, width: 1.0)),
|
||||||
focusedBorder: withBorder
|
focusedBorder: withBorder
|
||||||
? OutlineInputBorder(
|
? OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: primaryColor, width: 1.0),
|
borderSide: BorderSide(
|
||||||
|
color: borderColor ?? primaryColor, width: 1.0),
|
||||||
)
|
)
|
||||||
: UnderlineInputBorder(
|
: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(color: primaryColor, width: 1.0)),
|
borderSide: BorderSide(
|
||||||
|
color: borderColor ?? primaryColor, width: 1.0)),
|
||||||
|
disabledBorder: withBorder
|
||||||
|
? OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: borderColor ?? primaryColor, width: 1.0),
|
||||||
|
)
|
||||||
|
: UnderlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: borderColor ?? primaryColor, width: 1.0)),
|
||||||
),
|
),
|
||||||
validator: validator),
|
validator: validator),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -37,12 +37,14 @@ class LocalDropdown<T> extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(right: 18.0),
|
padding: const EdgeInsets.only(right: 18.0),
|
||||||
child: labelKey!=null? LocalText(
|
child: labelKey != null
|
||||||
context,
|
? LocalText(
|
||||||
labelKey!,
|
context,
|
||||||
color: Colors.black54,
|
labelKey!,
|
||||||
fontSize: 16,
|
color: Colors.black54,
|
||||||
): const SizedBox(),
|
fontSize: 16,
|
||||||
|
)
|
||||||
|
: const SizedBox(),
|
||||||
),
|
),
|
||||||
DropdownButton<T>(
|
DropdownButton<T>(
|
||||||
isDense: true,
|
isDense: true,
|
||||||
|
|||||||
33
lib/pages/widgets/local_radio.dart
Normal file
33
lib/pages/widgets/local_radio.dart
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../helpers/theme.dart';
|
||||||
|
|
||||||
|
class LocalRadio<T> extends StatelessWidget {
|
||||||
|
final Function(T?)? onChanged;
|
||||||
|
final T value;
|
||||||
|
final T? groupValue;
|
||||||
|
|
||||||
|
const LocalRadio(
|
||||||
|
{super.key, this.onChanged, required this.value, this.groupValue});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Radio<T>(
|
||||||
|
fillColor: MaterialStateProperty.resolveWith((states) {
|
||||||
|
// active
|
||||||
|
if (states.contains(MaterialState.selected)) {
|
||||||
|
return primaryColor;
|
||||||
|
}
|
||||||
|
// inactive
|
||||||
|
return labelColor;
|
||||||
|
}),
|
||||||
|
visualDensity: const VisualDensity(
|
||||||
|
horizontal: VisualDensity.minimumDensity,
|
||||||
|
vertical: VisualDensity.minimumDensity),
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
activeColor: primaryColor,
|
||||||
|
groupValue: groupValue,
|
||||||
|
value: value,
|
||||||
|
onChanged: onChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,6 +33,14 @@ class LocalRadioButtons<T> extends StatelessWidget {
|
|||||||
onTap: () => callback!(e),
|
onTap: () => callback!(e),
|
||||||
child: Row(children: <Widget>[
|
child: Row(children: <Widget>[
|
||||||
Radio<T>(
|
Radio<T>(
|
||||||
|
fillColor: MaterialStateProperty.resolveWith((states) {
|
||||||
|
// active
|
||||||
|
if (states.contains(MaterialState.selected)) {
|
||||||
|
return primaryColor;
|
||||||
|
}
|
||||||
|
// inactive
|
||||||
|
return labelColor;
|
||||||
|
}),
|
||||||
activeColor: primaryColor,
|
activeColor: primaryColor,
|
||||||
groupValue: selectedValue,
|
groupValue: selectedValue,
|
||||||
value: e,
|
value: e,
|
||||||
@@ -42,7 +50,7 @@ class LocalRadioButtons<T> extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Text(e.toString(),
|
Text(e.toString(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 15,
|
||||||
color:
|
color:
|
||||||
e == selectedValue ? primaryColor : Colors.black)),
|
e == selectedValue ? primaryColor : Colors.black)),
|
||||||
]),
|
]),
|
||||||
@@ -67,7 +75,14 @@ class LocalRadioButtons<T> extends StatelessWidget {
|
|||||||
e == selectedValue ? primaryColor : Colors.grey,
|
e == selectedValue ? primaryColor : Colors.grey,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(e.toString()),
|
Text(
|
||||||
|
e.toString(),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: e == selectedValue
|
||||||
|
? primaryColor
|
||||||
|
: Colors.black),
|
||||||
|
),
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
: Container())
|
: Container())
|
||||||
|
|||||||
Reference in New Issue
Block a user