From a66ecff159a06bb4f15ed9a644784fa42b480289 Mon Sep 17 00:00:00 2001 From: sma Date: Wed, 14 Feb 2024 16:54:38 +0630 Subject: [PATCH 1/3] add pinlogin_page and prepare profile --- assets/local/localization_en.json | 3 + assets/local/localization_mu.json | 3 + .../delivery_address_row.dart | 33 +++-- lib/pages/main/home_page.dart | 49 ++----- lib/pages/profile/profile_page.dart | 72 ++++++++++ lib/pages/signin/pinlogin_page.dart | 127 ++++++++++++++++++ 6 files changed, 240 insertions(+), 47 deletions(-) create mode 100644 lib/pages/signin/pinlogin_page.dart diff --git a/assets/local/localization_en.json b/assets/local/localization_en.json index 08838f9..1bae63f 100644 --- a/assets/local/localization_en.json +++ b/assets/local/localization_en.json @@ -31,6 +31,9 @@ "Welcome Start ================================================================":"", "welcome.signin":"Sign In", "welcome.msg":"Welcome to FCS!", + "welcome.pinlogin":"Login", + "welcome.pinlogin.fcsid":"Enter FCS ID", + "welcome.pinlogin.pin":"Enter Your PIN", "Welcome End ================================================================":"", "Contact Start ================================================================":"", diff --git a/assets/local/localization_mu.json b/assets/local/localization_mu.json index 323e8d1..f7134c4 100644 --- a/assets/local/localization_mu.json +++ b/assets/local/localization_mu.json @@ -29,6 +29,9 @@ "Welcome Start ================================================================":"", "welcome.signin":"ဝင်မည်", + "welcome.pinlogin":"ဝင်ရောက်ပါ", + "welcome.pinlogin.fcsid":"FCS ID ကိုရိုက်ထည့်ပါ", + "welcome.pinlogin.pin":"သင်၏ pin ကိုထည့်ပါ", "welcome.msg":"FCS က ကြိုဆိုပါတယ်!", "Welcome End ================================================================":"", diff --git a/lib/pages/delivery_address/delivery_address_row.dart b/lib/pages/delivery_address/delivery_address_row.dart index c6e248c..c096417 100644 --- a/lib/pages/delivery_address/delivery_address_row.dart +++ b/lib/pages/delivery_address/delivery_address_row.dart @@ -26,26 +26,35 @@ class DeliveryAddressRow extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + deliveryAddress.fullName!="" + ? line(context, deliveryAddress.fullName, iconData: MaterialCommunityIcons.account, - color: primaryColor, - fontSize: 16), + color: Colors.black, + fontSize: 16):SizedBox(), + deliveryAddress.phoneNumber!="" + ? line(context, deliveryAddress.phoneNumber, - iconData: Icons.phone, color: primaryColor, fontSize: 16), - SizedBox( - height: 5, - ), + iconData: Icons.phone, color: Colors.black, fontSize: 16):SizedBox(), + deliveryAddress.addressLine1!="" + ? line(context, deliveryAddress.addressLine1, - iconData: Icons.location_on), + iconData: Icons.location_on,color: Colors.black, fontSize: 16):SizedBox(), + deliveryAddress.addressLine2!="" + ? line( context, - deliveryAddress.addressLine2, - ), + deliveryAddress.addressLine2,color: Colors.black, fontSize: 16 + ):SizedBox(), + deliveryAddress.city!="" + ? line( context, - deliveryAddress.city, - ), - line(context, deliveryAddress.state), + deliveryAddress.city,color: Colors.black, fontSize: 16 + ):SizedBox(), + deliveryAddress.state!="" + ? + line(context, deliveryAddress.state,color: Colors.black, fontSize: 16):SizedBox(), ], ), ), diff --git a/lib/pages/main/home_page.dart b/lib/pages/main/home_page.dart index 85124a5..e7bd286 100644 --- a/lib/pages/main/home_page.dart +++ b/lib/pages/main/home_page.dart @@ -6,7 +6,6 @@ import 'package:fcs/domain/entities/package.dart'; import 'package:fcs/domain/entities/user.dart'; import 'package:fcs/helpers/shared_pref.dart'; import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/localization/transalation.dart'; import 'package:fcs/pages/carton/carton_list.dart'; import 'package:fcs/pages/chat/message_detail.dart'; import 'package:fcs/pages/chat/model/message_model.dart'; @@ -27,6 +26,7 @@ import 'package:fcs/pages/pickup/pickup_list.dart'; import 'package:fcs/pages/processing/processing_list.dart'; import 'package:fcs/pages/rates/shipment_rates.dart'; import 'package:fcs/pages/receiving/receiving_list.dart'; +import 'package:fcs/pages/signin/pinlogin_page.dart'; import 'package:fcs/pages/staff/staff_list.dart'; import 'package:fcs/pages/widgets/badge.dart'; import 'package:fcs/pages/widgets/bottom_widgets.dart'; @@ -366,25 +366,7 @@ class _HomePageState extends State { isSelected: isFcs, selectedBorderColor: Colors.white24, ); - final langToggle = ToggleButtons( - children: [ - Image.asset( - 'icons/flags/png/us.png', - package: 'country_icons', - fit: BoxFit.fitWidth, - width: 25, - ), - Image.asset( - 'icons/flags/png/mm.png', - package: 'country_icons', - fit: BoxFit.fitWidth, - width: 25, - ) - ], - onPressed: _langChange, - isSelected: languageModel.currentState, - selectedBorderColor: Colors.white24, - ); + final signinBtn = TextButton( onPressed: () { Navigator.of(context) @@ -402,6 +384,14 @@ class _HomePageState extends State { iconSize: 30, icon: Icon(Icons.account_circle,color: buttonColor,), ); + final pinLoginBtn = IconButton( + onPressed: () { + Navigator.of(context) + .push(CupertinoPageRoute(builder: (context) => PinLoginPage())); + }, + iconSize: 30, + icon: Icon(SimpleLineIcons.lock,color: buttonColor,), + ); var searchInput = Row(children: [ Expanded( @@ -478,17 +468,15 @@ class _HomePageState extends State { actions: login ? user.isCustomer() ? [ - langToggle, - profileBtn, + profileBtn, ] : [ fcsToggle, - langToggle, + pinLoginBtn, profileBtn, ] : [ - langToggle, - signinBtn, + signinBtn, ]), body: Container( decoration: BoxDecoration( @@ -518,16 +506,7 @@ class _HomePageState extends State { ); } - _langChange(index) { - var languageModel = Provider.of(context, listen: false); - languageModel.saveLanguage(Translation().supportedLanguages[index]); - setState(() { - isSelected.asMap().forEach((i, e) { - isSelected[i] = false; - }); - isSelected[index] = !isSelected[index]; - }); - } + _lookup() async { setState(() { diff --git a/lib/pages/profile/profile_page.dart b/lib/pages/profile/profile_page.dart index 9745223..ee34c96 100644 --- a/lib/pages/profile/profile_page.dart +++ b/lib/pages/profile/profile_page.dart @@ -13,6 +13,7 @@ import 'package:fcs/pages/widgets/defalut_delivery_address.dart'; import 'package:fcs/pages/widgets/display_text.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_text.dart'; import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -62,9 +63,11 @@ class _ProfileState extends State { @override Widget build(BuildContext context) { MainModel mainModel = Provider.of(context); + LanguageModel languageModel = Provider.of(context); if (mainModel.user == null) { return Container(); } + buildLanguage(languageModel); DeliveryAddressModel deliveryAddressModel = Provider.of(context); @@ -172,6 +175,12 @@ class _ProfileState extends State { builder: (context) => DeliveryAddressList())); }, ), + buildLanguageWidget( + context: context, + text: "profile.language", + iconData: Icons.language, + isEng: languageModel.isEng, + ), getPrivilegeBox(context), SizedBox(height: 15), logoutbutton, @@ -183,6 +192,69 @@ class _ProfileState extends State { ); } + Widget buildLanguageWidget( + {required String text, + required BuildContext context, + IconData? iconData, + required bool isEng}) { + return Row( + children: [ + Icon(iconData, color: primaryColor), + const SizedBox(width: 15), + Expanded( + child: LocalText( + context, + text, + fontSize: 15.0, + color: Colors.black54, + ), + ), + Row( + children: [ + isEng + ? Image.asset( + 'icons/flags/png/us.png', + package: 'country_icons', + fit: BoxFit.fitWidth, + width: 25, + ) + : Image.asset( + 'icons/flags/png/mm.png', + package: 'country_icons', + fit: BoxFit.fitWidth, + width: 25, + ), + Container( + width: 100, + padding: const EdgeInsets.only(left: 15), + child: DropdownButton( + value: selectedLanguage, + underline: const SizedBox(), + isExpanded: true, + items: languagesList + .map>((String value) { + return DropdownMenuItem( + value: value, + child: Text( + value, + style: const TextStyle(fontSize: 14), + )); + }).toList(), + onChanged: _selectedDropdown)), + ], + ) + ], + ); + } + + _selectedDropdown(selected) { + var languageModel = Provider.of(context, listen: false); + languageModel.saveLanguage(selected); + setState(() { + selectedLanguage = selected; + }); + } + Widget getPrivilegeBox(BuildContext context) { User? user = Provider.of(context, listen: false).user; List _privileges = diff --git a/lib/pages/signin/pinlogin_page.dart b/lib/pages/signin/pinlogin_page.dart new file mode 100644 index 0000000..87b171f --- /dev/null +++ b/lib/pages/signin/pinlogin_page.dart @@ -0,0 +1,127 @@ +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_app_bar.dart'; +import 'package:fcs/pages/widgets/local_button.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/material.dart'; +import 'package:pin_input_text_field/pin_input_text_field.dart'; + +class PinLoginPage extends StatefulWidget { + const PinLoginPage({super.key}); + + @override + State createState() => _PinLoginPageState(); +} + +class _PinLoginPageState extends State { + bool _isLoading = false; + late String pin; + late bool allNumberEntered; + @override + void initState() { + pin = ""; + allNumberEntered = false; + super.initState(); + } + + Widget build(BuildContext context) { + return LocalProgress( + inAsyncCall: _isLoading, + child: new Scaffold( + appBar: LocalAppBar( + backgroundColor: null, + arrowColor: Colors.black, + ), + body: _buildLogin(context)), + ); + } + + Widget _buildLogin(BuildContext context) { + return ListView( + padding: EdgeInsets.only(top: 20, left: 15, right: 15, bottom: 20), + children: [ + pinLoginLogo, + Padding( + padding: EdgeInsets.only(top: 20, bottom: 20), + child: Center( + child: LocalText( + context, + "welcome.pinlogin", + color: Colors.black, + fontSize: 18, + ), + ), + ), + LocalText( + context, + "welcome.pinlogin.fcsid", + color: Colors.grey, + ), + fcsIdBox, + Padding( + padding: EdgeInsets.only(top: 20, bottom: 20), + child: LocalText( + context, + "welcome.pinlogin.pin", + color: Colors.grey, + )), + Container( + child: PinInputTextField( + pinLength: 6, + decoration: BoxLooseDecoration( + strokeColorBuilder: PinListenColorBuilder( + primaryColor, Colors.grey.shade400)), + textInputAction: TextInputAction.done, + autoFocus: true, + onChanged: _pinChange, + ), + ), + loginBtn, + ]); + } + + final pinLoginLogo = Container( + width: 70, + height: 70, + child: FittedBox( + child: Image.asset( + "assets/logo.jpg", + ), + fit: BoxFit.fitHeight, + ), + ); + final fcsIdBox = Column( + children: [ + TextFormField( + // controller: controller, + style: textStyle, + cursorColor: primaryColor, + keyboardType: TextInputType.text, + decoration: new InputDecoration( + contentPadding: EdgeInsets.all(0), + labelStyle: newLabelStyle(color: Colors.black54, fontSize: 17), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide(color: primaryColor, width: 1.0)), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide(color: primaryColor, width: 1.0)), + disabledBorder: UnderlineInputBorder( + borderSide: BorderSide(color: primaryColor, width: 1.0)), + ), + ), + ], + ); + final loginBtn = Padding( + padding: EdgeInsets.only(top: 30), + child: LocalButton( + textKey: "welcome.pinlogin", + callBack: () {}, + ), + ); + + _pinChange(pin) { + setState(() { + this.pin = pin; + this.allNumberEntered = this.pin.length == 6; + }); + } +} From 13e6e232d56a7b6a11bce4543c2189dff852ce2c Mon Sep 17 00:00:00 2001 From: tzw Date: Wed, 14 Feb 2024 16:58:45 +0630 Subject: [PATCH 2/3] update staff list, add pin editor and privilege editor --- assets/local/localization_en.json | 8 + assets/local/localization_mu.json | 9 + lib/domain/constants.dart | 1 + lib/domain/entities/carton.dart | 1 - lib/domain/entities/user.dart | 8 +- .../carton/carton_image_upload_editor.dart | 45 ++-- lib/pages/carton/carton_info.dart | 54 +++-- lib/pages/carton/carton_size_widget.dart | 11 +- lib/pages/carton/mix_carton/type_widget.dart | 11 +- lib/pages/carton/model/carton_model.dart | 41 +++- lib/pages/discount/discount_editor.dart | 35 +-- lib/pages/discount/discount_list.dart | 21 +- lib/pages/fcs_shipment/fcs_shipment_info.dart | 10 +- lib/pages/main/util.dart | 1 - lib/pages/staff/model/staff_model.dart | 25 +++ lib/pages/staff/staff_editor.dart | 33 +-- lib/pages/staff/staff_info.dart | 203 ++++++++++++++++++ lib/pages/staff/staff_list.dart | 25 ++- lib/pages/staff/staff_pin_editor.dart | 192 +++++++++++++++++ lib/pages/staff/staff_privilege_editor.dart | 149 +++++++++++++ 20 files changed, 770 insertions(+), 113 deletions(-) create mode 100644 lib/pages/staff/staff_info.dart create mode 100644 lib/pages/staff/staff_pin_editor.dart create mode 100644 lib/pages/staff/staff_privilege_editor.dart diff --git a/assets/local/localization_en.json b/assets/local/localization_en.json index 08838f9..c117126 100644 --- a/assets/local/localization_en.json +++ b/assets/local/localization_en.json @@ -151,6 +151,14 @@ "staff.add":"Add", "staff.update":"Update", "staff.phone.search":"Enter phone number", + "staff.pin_login":"PIN Login", + "staff.edit_pin":"Edit PIN", + "staff.edit_privileges":"Edit Privileges", + "staff.privilege.title":"Privileges", + "staff.pin.title":"PIN", + "staff.new_pin":"New PIN", + "staff.confirm_pin":"Confirm PIN", + "staff.enable_pin":"Enable PIN Login", "Staff End ================================================================":"", "Profile Start ================================================================":"", diff --git a/assets/local/localization_mu.json b/assets/local/localization_mu.json index 323e8d1..41599cf 100644 --- a/assets/local/localization_mu.json +++ b/assets/local/localization_mu.json @@ -133,6 +133,7 @@ "customer.disable.btn":"ပိတ်ပါ", "customer.enable.btn":"ဖွင့်ပါ", "customer.chat.btn":"Chat", + "Customer End ================================================================":"", "Invitation Start ================================================================":"", @@ -151,6 +152,14 @@ "staff.add":"အသစ်ထည့်မည်", "staff.update":"ပြုပြင်မည်", "staff.phone.search":"ဖုန်းနံပါတ် ရိုက်ထည့်ပါ", + "staff.pin_login":"PIN Login", + "staff.edit_pin":"Edit PIN", + "staff.edit_privileges":"Edit Privileges", + "staff.privilege.title":"Privileges", + "staff.pin.title":"PIN", + "staff.new_pin":"New PIN", + "staff.confirm_pin":"Confirm PIN", + "staff.enable_pin":"Enable PIN Login", "Staff End ================================================================":"", "Profile Start ================================================================":"", diff --git a/lib/domain/constants.dart b/lib/domain/constants.dart index a96f1fe..1bf7bc6 100644 --- a/lib/domain/constants.dart +++ b/lib/domain/constants.dart @@ -34,6 +34,7 @@ const pkg_files_path = "/packages"; const shipment_labels_files_path = "/shipment_labels"; const receipt_labels_files_path = "/receipts"; const pickups_files_path = "/pickups"; +const carton_files_path = "/cartons"; // Link page const page_payment_methods = "payment_methods"; diff --git a/lib/domain/entities/carton.dart b/lib/domain/entities/carton.dart index 803be65..42ee221 100644 --- a/lib/domain/entities/carton.dart +++ b/lib/domain/entities/carton.dart @@ -47,7 +47,6 @@ class Carton { int weight; String? packageType; String? pickUpID; - List photos = []; List photoUrls; String? remark; DateTime? arrivedDate; diff --git a/lib/domain/entities/user.dart b/lib/domain/entities/user.dart index 9325bd5..e0c7826 100644 --- a/lib/domain/entities/user.dart +++ b/lib/domain/entities/user.dart @@ -19,6 +19,9 @@ class User { int userUnseenCount; int fcsUnseenCount; String? preferCurrency; + bool enablePinLogin; + String? pinDigit; + String? confirmPinDigit; String get initial => name != null && name != "" ? name!.substring(0, 1) : "?"; @@ -68,7 +71,10 @@ class User { this.lastMessageTime, this.userUnseenCount = 0, this.fcsUnseenCount = 0, - this.preferCurrency}); + this.preferCurrency, + this.enablePinLogin = false, + this.pinDigit, + this.confirmPinDigit}); factory User.fromJson(Map json) { return User( diff --git a/lib/pages/carton/carton_image_upload_editor.dart b/lib/pages/carton/carton_image_upload_editor.dart index 1abef1f..3be06aa 100644 --- a/lib/pages/carton/carton_image_upload_editor.dart +++ b/lib/pages/carton/carton_image_upload_editor.dart @@ -4,29 +4,29 @@ import 'package:fcs/pages/widgets/local_app_bar.dart'; import 'package:fcs/pages/widgets/multi_img_controller.dart'; import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../main/util.dart'; import '../widgets/local_button.dart'; import '../widgets/multi_img_file.dart'; - -typedef void FindCallBack(); +import 'model/carton_model.dart'; class CartonImageUploadEditor extends StatefulWidget { - final Carton? box; - const CartonImageUploadEditor({this.box}); + final Carton carton; + const CartonImageUploadEditor({required this.carton}); @override _CartonImageUploaState createState() => _CartonImageUploaState(); } class _CartonImageUploaState extends State { bool _isLoading = false; - Carton? _box; - MultiImgController multiImgController = MultiImgController(); + + MultiImgController _multiImgController = MultiImgController(); @override void initState() { super.initState(); - _box = widget.box; - multiImgController.setImageUrls = _box?.photoUrls; + _multiImgController.setImageUrls = widget.carton.photoUrls; } @override @@ -34,9 +34,10 @@ class _CartonImageUploaState extends State { final saveBtn = Padding( padding: const EdgeInsets.symmetric(horizontal: 30), child: LocalButton( - textKey: "btn.save", - callBack: () {}, - ), + textKey: "btn.save", + callBack: () { + _uploadImage(); + }), ); return LocalProgress( @@ -53,19 +54,37 @@ class _CartonImageUploaState extends State { child: ListView( children: [ Center( - child: Text("${_box?.cartonNumber}", + child: Text("${widget.carton.cartonNumber}", style: TextStyle( color: primaryColor, fontSize: 25, ))), MultiImageFile( enabled: true, - controller: multiImgController, + controller: _multiImgController, title: "Receipt File", ), + const SizedBox(height: 20), saveBtn, ], ), ))); } + + _uploadImage() async { + setState(() { + _isLoading = true; + }); + try { + await context.read().uploadCartonImages(widget.carton, + _multiImgController.getAddedFile, _multiImgController.getDeletedUrl); + Navigator.pop(context, true); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } } diff --git a/lib/pages/carton/carton_info.dart b/lib/pages/carton/carton_info.dart index c1488b8..8f125f2 100644 --- a/lib/pages/carton/carton_info.dart +++ b/lib/pages/carton/carton_info.dart @@ -34,7 +34,7 @@ class CartonInfo extends StatefulWidget { class _CartonInfoState extends State { final DateFormat dateFormat = DateFormat("d MMM yyyy"); final NumberFormat numberFormatter = NumberFormat("#,###"); - MultiImgController multiImgController = MultiImgController(); + MultiImgController _multiImgController = MultiImgController(); bool _isLoading = false; late Carton _carton; List _cargoTypes = []; @@ -58,7 +58,7 @@ class _CartonInfoState extends State { _carton.cartonType = carton_from_packages; _carton.billTo = billToConsignee; _carton.cartonSizeType = customCarton; - multiImgController.setImageUrls = _carton.photos; + _multiImgController.setImageUrls = _carton.photoUrls; _cargoTypes = _carton.cargoTypes.where((e) => !e.isCutomDuty).toList(); _surchareItems = _carton.cargoTypes.where((e) => e.isCutomDuty).toList(); if (_carton.cartonType == carton_from_packages) { @@ -245,7 +245,6 @@ class _CartonInfoState extends State { style: TextStyle(color: Colors.black54, fontSize: 15))) ], ), - //), Container( child: Padding( padding: const EdgeInsets.only(right: 60), @@ -273,7 +272,6 @@ class _CartonInfoState extends State { ); }).toList()), const SizedBox(height: 10), - ], ), ), @@ -283,29 +281,39 @@ class _CartonInfoState extends State { final img = MultiImageFile( enabled: false, - controller: multiImgController, + controller: _multiImgController, title: "Receipt File", ); final uploadImageBtn = Padding( padding: EdgeInsets.only(left: 200.0, right: 8.0), child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xff272262), - elevation: 3, - shape: - RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)), - minimumSize: Size(10, 35), - ), - onPressed: () { - Navigator.push( - context, - CupertinoPageRoute( - builder: (context) => CartonImageUploadEditor(box: _carton)), - ); - }, - child: const Text('Upload Images'), - ), + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xff272262), + elevation: 3, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0)), + minimumSize: Size(10, 35), + ), + onPressed: () async { + bool? updated = await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => + CartonImageUploadEditor(carton: _carton)), + ); + + if (updated ?? false) { + Carton? c = await context + .read() + .getCarton(widget.carton.id ?? ""); + if (c == null) return; + _carton = c; + _init(); + } + }, + child: LocalText(context, "box.imageupload.title", + color: Colors.white, fontSize: 14)), ); final deleteBtn = Padding( @@ -390,7 +398,9 @@ class _CartonInfoState extends State { _surchareItems.isEmpty ? const SizedBox() : surchargeItemBox, uploadImageBtn, img, - deleteBtn + const SizedBox(height: 15), + deleteBtn, + const SizedBox(height: 20) ])))); } diff --git a/lib/pages/carton/carton_size_widget.dart b/lib/pages/carton/carton_size_widget.dart index 54982f1..6b852e8 100644 --- a/lib/pages/carton/carton_size_widget.dart +++ b/lib/pages/carton/carton_size_widget.dart @@ -95,11 +95,18 @@ class _CartonSizeWidgetState extends State { _heightController.text = widget.height == null ? "0" : removeTrailingZeros(widget.height ?? 0); + _loadShipment(); + + if (mounted) { + setState(() {}); + } + } + + _loadShipment() async { var fcsShipments = await context.read().getActiveFcsShipments(); _shipments = fcsShipments; _shipment = widget.shipment; - if (mounted) { setState(() {}); } @@ -107,7 +114,7 @@ class _CartonSizeWidgetState extends State { @override void didUpdateWidget(covariant CartonSizeWidget oldWidget) { - _init(); + _loadShipment(); super.didUpdateWidget(oldWidget); } diff --git a/lib/pages/carton/mix_carton/type_widget.dart b/lib/pages/carton/mix_carton/type_widget.dart index 4484c68..331d2b5 100644 --- a/lib/pages/carton/mix_carton/type_widget.dart +++ b/lib/pages/carton/mix_carton/type_widget.dart @@ -76,11 +76,18 @@ class _TypeWidgetState extends State { _heightController.text = widget.height == null ? "0" : removeTrailingZeros(widget.height ?? 0); + _loadShipment(); + + if (mounted) { + setState(() {}); + } + } + + _loadShipment() async { var fcsShipments = await context.read().getActiveFcsShipments(); _shipments = fcsShipments; _shipment = widget.shipment; - if (mounted) { setState(() {}); } @@ -88,7 +95,7 @@ class _TypeWidgetState extends State { @override void didUpdateWidget(covariant TypeWidget oldWidget) { - _init(); + _loadShipment(); super.didUpdateWidget(oldWidget); } diff --git a/lib/pages/carton/model/carton_model.dart b/lib/pages/carton/model/carton_model.dart index 736b48e..fe98399 100644 --- a/lib/pages/carton/model/carton_model.dart +++ b/lib/pages/carton/model/carton_model.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:io'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fcs/data/services/services.dart'; @@ -10,6 +11,8 @@ import 'package:fcs/pagination/paginator_listener.dart'; import 'package:logging/logging.dart'; import '../../../domain/entities/user.dart'; +import '../../../helpers/firebase_helper.dart'; +import 'package:path/path.dart' as Path; class CartonModel extends BaseModel { final log = Logger('CartonModel'); @@ -227,7 +230,7 @@ class CartonModel extends BaseModel { return Services.instance.cartonService.searchCarton(term); } - Future> getCartonsByIds(List cartonIds) async { + Future> getCartonsByIds(List cartonIds) async { List cartons = []; try { for (var e in cartonIds) { @@ -241,4 +244,40 @@ class CartonModel extends BaseModel { } return cartons; } + + Future uploadCartonImages( + Carton carton, List files, List deletedUrls) async { + if (deletedUrls.isNotEmpty) { + for (String? url in deletedUrls) { + carton.photoUrls.remove(url); + } + } + + List uploadedURL = []; + if (files.isNotEmpty) { + var count = + (carton.photoUrls.length) + files.length - (deletedUrls.length); + + if (count > uploadPhotoLimit) + throw Exception("Exceed number of file upload"); + + carton.photoUrls = carton.photoUrls; + String path = Path.join(carton_files_path); + uploadedURL = await uploadFiles(path, files); + uploadedURL.forEach((url) { + carton.photoUrls.add(url); + }); + } + try { + // await Services.instance.packageService.updateReceiving(package); + } catch (e) { + // delete newly uploaded photos if fails + try { + deleteStorageFromUrls(uploadedURL); + carton.photoUrls.removeWhere((i) => uploadedURL.contains(i)); + } catch (e) {} + throw e; + } + return deleteStorageFromUrls(deletedUrls); + } } diff --git a/lib/pages/discount/discount_editor.dart b/lib/pages/discount/discount_editor.dart index 4511576..f18a059 100644 --- a/lib/pages/discount/discount_editor.dart +++ b/lib/pages/discount/discount_editor.dart @@ -1,13 +1,12 @@ import 'package:fcs/domain/entities/discount.dart'; import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/localization/app_translations.dart'; import 'package:fcs/pages/discount/model/discount_model.dart'; import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/user_search/user_search.dart'; import 'package:fcs/pages/widgets/display_text.dart'; import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_app_bar.dart'; import 'package:fcs/pages/widgets/progress.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -88,29 +87,17 @@ class _DiscountEditorState extends State { inAsyncCall: _isLoading, child: Scaffold( backgroundColor: Colors.white, - appBar: AppBar( - centerTitle: true, - title: Text( - AppTranslations.of(context)!.text("discount.form"), - ), - leading: new IconButton( - icon: new Icon(CupertinoIcons.back), - onPressed: () { - if (isDataChanged()) { - showConfirmDialog(context, "back.button_confirm", () { - Navigator.of(context).pop(); - }); - } else { - Navigator.of(context).pop(); - } - }, - ), - backgroundColor: primaryColor, + appBar: LocalAppBar( + labelKey: "discount.form", + backgroundColor: Colors.white, + arrowColor: primaryColor, + labelColor: primaryColor, actions: [ - IconButton( - icon: Icon(Icons.delete), - onPressed: _delete, - ) + _isNew + ? const SizedBox() + : IconButton( + icon: Icon(Icons.delete, color: primaryColor), + onPressed: _delete) ], ), body: Padding( diff --git a/lib/pages/discount/discount_list.dart b/lib/pages/discount/discount_list.dart index e789ce7..8d4ce9d 100644 --- a/lib/pages/discount/discount_list.dart +++ b/lib/pages/discount/discount_list.dart @@ -1,7 +1,7 @@ import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/localization/app_translations.dart'; import 'package:fcs/pages/discount/discount_list_row.dart'; import 'package:fcs/pages/discount/model/discount_model.dart'; +import 'package:fcs/pages/widgets/local_app_bar.dart'; import 'package:fcs/pages/widgets/local_popup_menu_button.dart'; import 'package:fcs/domain/vo/local_popupmenu.dart'; import 'package:fcs/pages/widgets/local_text.dart'; @@ -58,26 +58,13 @@ class _DiscountListState extends State { return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( - appBar: AppBar( - centerTitle: true, - title: Text( - AppTranslations.of(context)!.text("discount.title"), - ), - leading: new IconButton( - icon: new Icon(CupertinoIcons.back), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - actions: [popupMenu], - ), + appBar: LocalAppBar(labelKey: "discount.title", actions: [popupMenu]), body: Column( children: [ Expanded( child: ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - height: 1, - ), + separatorBuilder: (context, index) => + Divider(color: Colors.black, height: 1), controller: _controller, itemCount: discountModel.discounts.length, itemBuilder: (BuildContext context, int index) { diff --git a/lib/pages/fcs_shipment/fcs_shipment_info.dart b/lib/pages/fcs_shipment/fcs_shipment_info.dart index 9d14633..1ae5354 100644 --- a/lib/pages/fcs_shipment/fcs_shipment_info.dart +++ b/lib/pages/fcs_shipment/fcs_shipment_info.dart @@ -135,7 +135,7 @@ class _FcsShipmentInfoState extends State { padding: const EdgeInsets.symmetric(horizontal: 30), child: LocalButton( textKey: "FCSshipment.process.btn", - callBack: _ship, + callBack: _ship, ), ); final arriveBtn = Padding( @@ -184,7 +184,7 @@ class _FcsShipmentInfoState extends State { body: Card( elevation: 0, child: Padding( - padding: const EdgeInsets.all(10.0), + padding: const EdgeInsets.only(left: 12.0, right: 12), child: ListView(children: [ statusBox, Row(mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -217,13 +217,13 @@ class _FcsShipmentInfoState extends State { ? Container( padding: EdgeInsets.only(top: 3), child: cancelBtn) : Container(), - _fcsShipment?.status == fcs_shipment_processing_status + _fcsShipment?.status == fcs_shipment_processing_status ? shipBtn : Container(), - _fcsShipment?.status == fcs_shipment_shipped_status + _fcsShipment?.status == fcs_shipment_shipped_status ? arriveBtn : Container(), - _fcsShipment?.status == fcs_shipment_arrived_status + _fcsShipment?.status == fcs_shipment_arrived_status ? invoiceBtn : Container(), SizedBox( diff --git a/lib/pages/main/util.dart b/lib/pages/main/util.dart index 9e28cbb..a4fc2bb 100644 --- a/lib/pages/main/util.dart +++ b/lib/pages/main/util.dart @@ -396,7 +396,6 @@ bool hasUnicode(String text) { return unicodeSymbols.length > 0; } - String removeTrailingZeros(double number) { String result = number.toString(); result = result.indexOf('.') > 0 diff --git a/lib/pages/staff/model/staff_model.dart b/lib/pages/staff/model/staff_model.dart index fabf82b..705737a 100644 --- a/lib/pages/staff/model/staff_model.dart +++ b/lib/pages/staff/model/staff_model.dart @@ -106,4 +106,29 @@ class StaffModel extends BaseModel { } return users; } + + Future getUser(String userID) async { + if (userID == "") return null; + + String path = "/$user_collection"; + try { + var snap = await FirebaseFirestore.instance + .collection(path) + .doc(userID) + .get(const GetOptions(source: Source.server)); + + if (snap.data() == null) return null; + Map? data = snap.data() as Map; + + if (data['delete_time'] == 0) { + User user = User.fromMap(data, snap.id); + return user; + } else { + return null; + } + } catch (e) { + log.warning("Error!! $e"); + } + return null; + } } diff --git a/lib/pages/staff/staff_editor.dart b/lib/pages/staff/staff_editor.dart index d5531b8..7752fc2 100644 --- a/lib/pages/staff/staff_editor.dart +++ b/lib/pages/staff/staff_editor.dart @@ -72,7 +72,7 @@ class _StaffEditorState extends State { }), Padding( padding: const EdgeInsets.only(right: 8.0), - child: Icon(p.iconData, size: 50, color: Colors.black38), + child: Icon(p.iconData, size: 30, color: Colors.black38), ), Expanded( child: Column( @@ -80,10 +80,10 @@ class _StaffEditorState extends State { children: [ new Text( p.name ?? "", - style: TextStyle(fontSize: 15.0, color: primaryColor), + style: TextStyle(fontSize: 15.0, color: Colors.black), ), Text(p.desc ?? "", - style: TextStyle(fontSize: 13, color: Colors.grey[600])) + style: TextStyle(fontSize: 13, color: labelColor)) ], ), ), @@ -155,15 +155,22 @@ class _StaffEditorState extends State { ], ); - final updateButton = fcsButton( - context, - getLocalString(context, 'staff.update'), - callack: _save, + final updateButton = Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: fcsButton( + context, + getLocalString(context, 'staff.update'), + callack: _save, + ), ); - final addButton = fcsButton( - context, - getLocalString(context, 'staff.add'), - callack: _add, + + final addButton = Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: fcsButton( + context, + getLocalString(context, 'staff.add'), + callack: _add, + ), ); return LocalProgress( @@ -196,9 +203,7 @@ class _StaffEditorState extends State { Container( child: isNew ? addButton : updateButton, ), - SizedBox( - height: 10, - ) + SizedBox(height: 20) ], ), ), diff --git a/lib/pages/staff/staff_info.dart b/lib/pages/staff/staff_info.dart new file mode 100644 index 0000000..94f690c --- /dev/null +++ b/lib/pages/staff/staff_info.dart @@ -0,0 +1,203 @@ +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/domain/vo/privilege.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/staff/model/staff_model.dart'; +import 'package:fcs/pages/widgets/display_text.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_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_vector_icons/flutter_vector_icons.dart'; +import 'package:provider/provider.dart'; + +import 'staff_pin_editor.dart'; +import 'staff_privilege_editor.dart'; + +class StaffInfo extends StatefulWidget { + final User staff; + const StaffInfo({required this.staff}); + @override + _StaffInfoState createState() => _StaffInfoState(); +} + +class _StaffInfoState extends State { + bool _isLoading = false; + late User _staff; + List _privileges = []; + + @override + void initState() { + _staff = widget.staff; + _init(); + super.initState(); + } + + _init() { + List list = + Provider.of(context, listen: false).privileges; + list.forEach((p) => _staff.privileges.contains(p.id) + ? p.isChecked = true + : p.isChecked = false); + _privileges = list.where((e) => e.isChecked ?? false).toList(); + if (mounted) { + setState(() {}); + } + } + + List showprivilegeList(BuildContext context) { + return _privileges.map((p) { + return new ListTile( + title: new Row( + children: [ + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Icon(p.iconData, size: 30, color: Colors.black38), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + new Text( + p.name ?? "", + style: TextStyle(fontSize: 15.0, color: Colors.black), + ), + Text(p.desc ?? "", + style: TextStyle(fontSize: 13, color: labelColor)) + ], + ), + ), + ], + )); + }).toList(); + } + + @override + Widget build(BuildContext context) { + final fcsIdBox = DisplayText( + text: _staff.fcsID, + labelTextKey: "customer.fcs.id", + icon: FcsIDIcon(), + ); + + final namebox = DisplayText( + text: _staff.name, + labelTextKey: "customer.name", + iconData: Icons.person, + ); + + final phoneNumberBox = Row( + children: [ + Expanded( + child: DisplayText( + text: _staff.phoneNumber, + labelTextKey: "customer.phone", + iconData: Icons.phone, + )), + IconButton( + icon: Icon(Icons.open_in_new, color: primaryColor), + onPressed: () => call(context, _staff.phoneNumber!)), + ], + ); + + final pinBox = Row( + children: [ + Expanded( + child: DisplayText( + text: _staff.enablePinLogin ? "Enabled" : "Disabled", + labelTextKey: "staff.pin_login", + iconData: MaterialCommunityIcons.lock)), + SizedBox( + width: 65, + height: 35, + child: OutlinedButton( + style: OutlinedButton.styleFrom( + padding: EdgeInsets.all(5), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0)), + side: BorderSide(color: primaryColor), + ), + onPressed: () async { + bool? updated = await Navigator.of(context).push( + CupertinoPageRoute( + builder: (context) => StaffPinEditor(staff: _staff))); + + if (updated ?? false) { + User? _u = + await context.read().getUser(widget.staff.id!); + if (_u == null) return; + _staff = _u; + _init(); + } + }, + child: LocalText(context, 'staff.edit_pin', + color: primaryColor, fontSize: 13), + ), + ) + ], + ); + + final privilegeTitleBox = Row( + children: [ + Expanded( + child: LocalText(context, 'staff.privilege.title', + color: Colors.black54, fontSize: 15)), + SizedBox( + width: 100, + height: 35, + child: OutlinedButton( + style: OutlinedButton.styleFrom( + padding: EdgeInsets.all(5), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0)), + side: BorderSide(color: primaryColor), + ), + onPressed: () async { + bool? updated = await Navigator.of(context).push( + CupertinoPageRoute( + builder: (context) => + StaffPrivilegeEditor(staff: _staff))); + + if (updated ?? false) { + User? _u = + await context.read().getUser(widget.staff.id!); + if (_u == null) return; + _staff = _u; + _init(); + } + }, + child: LocalText(context, 'staff.edit_privileges', + color: primaryColor, fontSize: 13), + ), + ) + ], + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: LocalAppBar( + labelKey: "staff.form.title", + backgroundColor: Colors.white, + labelColor: primaryColor, + arrowColor: primaryColor), + body: Padding( + padding: const EdgeInsets.only(left: 12.0, right: 12), + child: ListView( + children: [ + fcsIdBox, + phoneNumberBox, + namebox, + pinBox, + const SizedBox(height: 10), + privilegeTitleBox, + Column(children: showprivilegeList(context)), + SizedBox(height: 30) + ], + ), + ), + )); + } +} diff --git a/lib/pages/staff/staff_list.dart b/lib/pages/staff/staff_list.dart index fc7c7a6..f5e6be0 100644 --- a/lib/pages/staff/staff_list.dart +++ b/lib/pages/staff/staff_list.dart @@ -12,6 +12,7 @@ import 'package:provider/provider.dart'; import '../../pagination/paginator_listview.dart'; import 'staff_editor.dart'; +import 'staff_info.dart'; class StaffList extends StatefulWidget { @override @@ -57,23 +58,19 @@ class _StaffListState extends State { return InkWell( onTap: () { Navigator.of(context).push( - CupertinoPageRoute(builder: (context) => StaffEditor(staff: user))); + CupertinoPageRoute(builder: (context) => StaffInfo(staff: user))); }, child: Row( children: [ Expanded( child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 10.0), + padding: const EdgeInsets.symmetric(vertical: 8.0), child: new Row( children: [ new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 32.0 - dotSize / 2), - child: Icon( - MaterialCommunityIcons.account_hard_hat, - color: primaryColor, - size: 40, - ), + padding: new EdgeInsets.symmetric(horizontal: 15), + child: Icon(MaterialCommunityIcons.account_hard_hat, + color: primaryColor, size: 30), ), new Expanded( child: new Column( @@ -84,7 +81,15 @@ class _StaffListState extends State { style: new TextStyle(fontSize: 15.0), ), Padding( - padding: const EdgeInsets.only(top: 8.0), + padding: const EdgeInsets.only(top: 2), + child: new Text( + user.fcsID ?? "", + style: new TextStyle( + fontSize: 15.0, color: Colors.grey), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 2), child: new Text( user.phoneNumber ?? "", style: new TextStyle( diff --git a/lib/pages/staff/staff_pin_editor.dart b/lib/pages/staff/staff_pin_editor.dart new file mode 100644 index 0000000..34e4c3c --- /dev/null +++ b/lib/pages/staff/staff_pin_editor.dart @@ -0,0 +1,192 @@ +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_app_bar.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/material.dart'; +import 'package:pin_input_text_field/pin_input_text_field.dart'; + +import '../main/util.dart'; +import '../widgets/local_text.dart'; + +class StaffPinEditor extends StatefulWidget { + final User staff; + const StaffPinEditor({required this.staff}); + @override + _StaffPinEditorState createState() => _StaffPinEditorState(); +} + +class _StaffPinEditorState extends State { + bool _isLoading = false; + late User _staff; + bool _enablePinLogin = false; + String _newPin = ""; + String _confirmPin = ""; + + @override + void initState() { + _staff = widget.staff; + _enablePinLogin = _staff.enablePinLogin; + _newPin = _staff.pinDigit ?? ""; + _confirmPin = _staff.confirmPinDigit ?? ""; + super.initState(); + } + + @override + Widget build(BuildContext context) { + final enablePinBox = Row( + children: [ + Checkbox( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + visualDensity: const VisualDensity( + horizontal: VisualDensity.minimumDensity, + vertical: VisualDensity.minimumDensity), + activeColor: primaryColor, + side: BorderSide(color: Colors.black38, width: 2), + value: _enablePinLogin, + onChanged: (value) { + setState(() { + _enablePinLogin = value ?? false; + }); + }, + ), + const SizedBox(width: 15), + LocalText(context, 'staff.enable_pin', + fontSize: 15, color: Colors.black) + ], + ); + + final newPinBox = Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocalText(context, 'staff.new_pin', + color: Colors.black54, fontSize: 15), + const SizedBox(height: 8), + PinInputTextField( + cursor: Cursor( + color: primaryColor, enabled: true, width: 2, height: 30), + pinLength: 6, + decoration: BoxLooseDecoration( + strokeColorBuilder: + PinListenColorBuilder(primaryColor, Colors.grey.shade400)), + textInputAction: TextInputAction.done, + autoFocus: true, + onChanged: _newPinChange), + ], + ); + + final confirmPinBox = Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocalText(context, 'staff.confirm_pin', + color: Colors.black54, fontSize: 15), + const SizedBox(height: 8), + PinInputTextField( + pinLength: 6, + cursor: Cursor( + color: primaryColor, enabled: true, width: 2, height: 30), + decoration: BoxLooseDecoration( + strokeColorBuilder: + PinListenColorBuilder(primaryColor, Colors.grey.shade400)), + textInputAction: TextInputAction.done, + autoFocus: false, + onChanged: _confirmPinChange), + ], + ); + + final saveButton = Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: fcsButton( + context, + getLocalString(context, 'btn.save'), + callack: _save, + ), + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: LocalAppBar( + labelKey: "staff.pin.title", + backgroundColor: Colors.white, + labelColor: primaryColor, + arrowColor: primaryColor), + body: Padding( + padding: const EdgeInsets.only(left: 15.0, right: 15), + child: ListView( + children: [ + Column( + children: [ + Text(_staff.name ?? "", + style: TextStyle(color: Colors.black, fontSize: 18)), + Text(_staff.fcsID ?? "", + style: TextStyle(color: Colors.black, fontSize: 15)), + ], + ), + const SizedBox(height: 20), + enablePinBox, + const SizedBox(height: 30), + newPinBox, + SizedBox(height: 30), + confirmPinBox, + SizedBox(height: 30), + saveButton, + SizedBox(height: 30) + ], + ), + ), + )); + } + + _newPinChange(pin) { + setState(() { + this._newPin = pin; + }); + } + + _confirmPinChange(pin) { + setState(() { + this._confirmPin = pin; + }); + } + + _save() async { + if (_newPin == "") { + showMsgDialog(context, "Error", "Invalid new PIN"); + return; + } + + if (_newPin.length < 6) { + showMsgDialog(context, "Error", "New PIN must be 6 digits"); + return; + } + + if (_confirmPin == "") { + showMsgDialog(context, "Error", "Invalid confirm PIN"); + return; + } + + if (_confirmPin.length < 6) { + showMsgDialog(context, "Error", "Confirm PIN must be 6 digits"); + return; + } + + if (_confirmPin != _newPin) { + showMsgDialog(context, "Error", "Those pins didn’t match. Try again."); + return; + } + + setState(() { + _isLoading = true; + }); + + try { + Navigator.pop(context, true); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/staff/staff_privilege_editor.dart b/lib/pages/staff/staff_privilege_editor.dart new file mode 100644 index 0000000..fc9697e --- /dev/null +++ b/lib/pages/staff/staff_privilege_editor.dart @@ -0,0 +1,149 @@ +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/domain/vo/privilege.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/staff/model/staff_model.dart'; +import 'package:fcs/pages/widgets/local_app_bar.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../main/util.dart'; +import '../widgets/local_text.dart'; + +class StaffPrivilegeEditor extends StatefulWidget { + final User staff; + const StaffPrivilegeEditor({required this.staff}); + @override + _StaffPrivilegeEditorState createState() => _StaffPrivilegeEditorState(); +} + +class _StaffPrivilegeEditorState extends State { + bool _isLoading = false; + late User _staff; + List _privileges = []; + + @override + void initState() { + _staff = widget.staff; + _privileges = Provider.of(context, listen: false).privileges; + _privileges.forEach((p) => _staff.privileges.contains(p.id) + ? p.isChecked = true + : p.isChecked = false); + super.initState(); + } + + List showprivilegeList(BuildContext context) { + return _privileges.map((p) { + return new ListTile( + title: InkWell( + onTap: () { + setState(() { + p.isChecked = p.isChecked == null ? true : !p.isChecked!; + }); + }, + child: new Row( + children: [ + new Checkbox( + value: p.isChecked == null ? false : p.isChecked, + activeColor: primaryColor, + side: BorderSide(color: Colors.black38, width: 2), + onChanged: (bool? value) { + if (value != null) + setState(() { + p.isChecked = value; + }); + }), + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Icon(p.iconData, size: 30, color: Colors.black38), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + new Text( + p.name ?? "", + style: TextStyle(fontSize: 15.0, color: Colors.black), + ), + Text(p.desc ?? "", + style: TextStyle(fontSize: 13, color: labelColor)) + ], + ), + ), + ], + ), + )); + }).toList(); + } + + @override + Widget build(BuildContext context) { + final saveButton = Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: fcsButton( + context, + getLocalString(context, 'btn.save'), + callack: _save, + ), + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: LocalAppBar( + labelKey: "staff.privilege.title", + backgroundColor: Colors.white, + labelColor: primaryColor, + arrowColor: primaryColor), + body: Padding( + padding: const EdgeInsets.only(left: 12.0, right: 12), + child: ListView( + children: [ + Column( + children: [ + Text(_staff.name ?? "", + style: TextStyle(color: Colors.black, fontSize: 18)), + Text(_staff.fcsID ?? "", + style: TextStyle(color: Colors.black, fontSize: 15)), + ], + ), + const SizedBox(height: 10), + LocalText(context, 'staff.privilege.title', + color: Colors.black54, fontSize: 15), + Column( + children: showprivilegeList(context), + ), + saveButton, + SizedBox(height: 20) + ], + ), + ), + )); + } + + List privilegesIDs() { + return this + ._privileges + .where((p) => p.isChecked!) + .map((p) => p.id) + .toList(); + } + + _save() async { + setState(() { + _isLoading = true; + }); + + StaffModel staffModel = Provider.of(context, listen: false); + try { + await staffModel.updatePrivileges(widget.staff.id!, privilegesIDs()); + Navigator.pop(context, true); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} From 86aedb42afd86dc62f969aa6316efeb10004a44e Mon Sep 17 00:00:00 2001 From: tzw Date: Wed, 14 Feb 2024 17:19:55 +0630 Subject: [PATCH 3/3] update pin login --- .../delivery_address_row.dart | 2 - lib/pages/main/home_page.dart | 29 +-- lib/pages/signin/pinlogin_page.dart | 165 +++++++++--------- lib/pages/staff/staff_pin_editor.dart | 6 +- 4 files changed, 99 insertions(+), 103 deletions(-) diff --git a/lib/pages/delivery_address/delivery_address_row.dart b/lib/pages/delivery_address/delivery_address_row.dart index c096417..2056ddc 100644 --- a/lib/pages/delivery_address/delivery_address_row.dart +++ b/lib/pages/delivery_address/delivery_address_row.dart @@ -1,7 +1,5 @@ import 'package:fcs/domain/vo/delivery_address.dart'; -import 'package:fcs/helpers/theme.dart'; import 'package:fcs/pages/widgets/local_text.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart'; diff --git a/lib/pages/main/home_page.dart b/lib/pages/main/home_page.dart index e7bd286..c1ad000 100644 --- a/lib/pages/main/home_page.dart +++ b/lib/pages/main/home_page.dart @@ -357,7 +357,7 @@ class _HomePageState extends State { selectedColor: Colors.white, color: Colors.blue, children: [ - Icon(MaterialCommunityIcons.account_tie), + Icon(MaterialCommunityIcons.account_tie,size: 25), ], onPressed: (i) => this.setState(() { isFcs[0] = !isFcs[0]; @@ -366,7 +366,7 @@ class _HomePageState extends State { isSelected: isFcs, selectedBorderColor: Colors.white24, ); - + final signinBtn = TextButton( onPressed: () { Navigator.of(context) @@ -381,16 +381,23 @@ class _HomePageState extends State { onPressed: () { Navigator.of(context).push(RightLeftPageRoute(Profile())); }, - iconSize: 30, - icon: Icon(Icons.account_circle,color: buttonColor,), + iconSize: 25, + icon: Icon( + Icons.account_circle, + color: buttonColor, + ), ); + final pinLoginBtn = IconButton( onPressed: () { Navigator.of(context) .push(CupertinoPageRoute(builder: (context) => PinLoginPage())); }, - iconSize: 30, - icon: Icon(SimpleLineIcons.lock,color: buttonColor,), + iconSize: 25, + icon: Icon( + Icons.lock_outline, + color: buttonColor, + ), ); var searchInput = Row(children: [ @@ -468,15 +475,15 @@ class _HomePageState extends State { actions: login ? user.isCustomer() ? [ - profileBtn, + profileBtn, ] : [ - fcsToggle, pinLoginBtn, + fcsToggle, profileBtn, ] : [ - signinBtn, + signinBtn, ]), body: Container( decoration: BoxDecoration( @@ -506,8 +513,6 @@ class _HomePageState extends State { ); } - - _lookup() async { setState(() { _isLoading = true; @@ -515,7 +520,7 @@ class _HomePageState extends State { try { String term = _searchCtl.text; - if ( term.trim() == "") return; + if (term.trim() == "") return; var packageModel = Provider.of(context, listen: false); Package? package = await packageModel.lookupPackage(term); if (package == null) { diff --git a/lib/pages/signin/pinlogin_page.dart b/lib/pages/signin/pinlogin_page.dart index 87b171f..e03d1e5 100644 --- a/lib/pages/signin/pinlogin_page.dart +++ b/lib/pages/signin/pinlogin_page.dart @@ -16,15 +16,52 @@ class PinLoginPage extends StatefulWidget { class _PinLoginPageState extends State { bool _isLoading = false; late String pin; - late bool allNumberEntered; + TextEditingController _fcsIdCtl = new TextEditingController(); + @override void initState() { pin = ""; - allNumberEntered = false; super.initState(); } Widget build(BuildContext context) { + final fcsIdBox = TextFormField( + controller: _fcsIdCtl, + autofocus: true, + style: TextStyle( + fontSize: 15, color: Colors.black87, fontWeight: FontWeight.w500), + cursorColor: primaryColor, + keyboardType: TextInputType.text, + decoration: new InputDecoration( + contentPadding: EdgeInsets.all(0), + labelStyle: newLabelStyle(color: Colors.black54, fontSize: 17), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide(color: primaryColor, width: 1.0)), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide(color: primaryColor, width: 1.0)), + disabledBorder: UnderlineInputBorder( + borderSide: BorderSide(color: primaryColor, width: 1.0)), + ), + ); + + final pinLoginLogo = Container( + width: 70, + height: 70, + child: FittedBox( + child: Image.asset( + "assets/logo.jpg", + ), + fit: BoxFit.fitHeight, + ), + ); + + final loginBtn = Padding( + padding: EdgeInsets.only(top: 30), + child: LocalButton( + textKey: "welcome.pinlogin", + callBack: () {}, + ), + ); return LocalProgress( inAsyncCall: _isLoading, child: new Scaffold( @@ -32,96 +69,52 @@ class _PinLoginPageState extends State { backgroundColor: null, arrowColor: Colors.black, ), - body: _buildLogin(context)), + body: ListView( + padding: EdgeInsets.only(top: 20, left: 15, right: 15, bottom: 20), + children: [ + pinLoginLogo, + Padding( + padding: EdgeInsets.only(top: 20, bottom: 20), + child: Center( + child: LocalText(context, "welcome.pinlogin", + color: Colors.black, fontSize: 18), + ), + ), + LocalText( + context, + "welcome.pinlogin.fcsid", + color: Colors.black54, + fontSize: 15, + ), + fcsIdBox, + Padding( + padding: EdgeInsets.only(top: 25, bottom: 20), + child: LocalText( + context, + "welcome.pinlogin.pin", + color: Colors.black54, + fontSize: 15, + )), + PinInputTextField( + cursor: Cursor( + color: primaryColor, enabled: true, width: 2, height: 23), + pinLength: 6, + decoration: BoxLooseDecoration( + strokeColorBuilder: PinListenColorBuilder( + primaryColor, Colors.grey.shade400)), + textInputAction: TextInputAction.done, + autoFocus: false, + onChanged: _pinChange, + ), + loginBtn, + ], + )), ); } - Widget _buildLogin(BuildContext context) { - return ListView( - padding: EdgeInsets.only(top: 20, left: 15, right: 15, bottom: 20), - children: [ - pinLoginLogo, - Padding( - padding: EdgeInsets.only(top: 20, bottom: 20), - child: Center( - child: LocalText( - context, - "welcome.pinlogin", - color: Colors.black, - fontSize: 18, - ), - ), - ), - LocalText( - context, - "welcome.pinlogin.fcsid", - color: Colors.grey, - ), - fcsIdBox, - Padding( - padding: EdgeInsets.only(top: 20, bottom: 20), - child: LocalText( - context, - "welcome.pinlogin.pin", - color: Colors.grey, - )), - Container( - child: PinInputTextField( - pinLength: 6, - decoration: BoxLooseDecoration( - strokeColorBuilder: PinListenColorBuilder( - primaryColor, Colors.grey.shade400)), - textInputAction: TextInputAction.done, - autoFocus: true, - onChanged: _pinChange, - ), - ), - loginBtn, - ]); - } - - final pinLoginLogo = Container( - width: 70, - height: 70, - child: FittedBox( - child: Image.asset( - "assets/logo.jpg", - ), - fit: BoxFit.fitHeight, - ), - ); - final fcsIdBox = Column( - children: [ - TextFormField( - // controller: controller, - style: textStyle, - cursorColor: primaryColor, - keyboardType: TextInputType.text, - decoration: new InputDecoration( - contentPadding: EdgeInsets.all(0), - labelStyle: newLabelStyle(color: Colors.black54, fontSize: 17), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - disabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - ), - ], - ); - final loginBtn = Padding( - padding: EdgeInsets.only(top: 30), - child: LocalButton( - textKey: "welcome.pinlogin", - callBack: () {}, - ), - ); - _pinChange(pin) { setState(() { this.pin = pin; - this.allNumberEntered = this.pin.length == 6; }); } } diff --git a/lib/pages/staff/staff_pin_editor.dart b/lib/pages/staff/staff_pin_editor.dart index 34e4c3c..a2a73b6 100644 --- a/lib/pages/staff/staff_pin_editor.dart +++ b/lib/pages/staff/staff_pin_editor.dart @@ -63,7 +63,7 @@ class _StaffPinEditorState extends State { const SizedBox(height: 8), PinInputTextField( cursor: Cursor( - color: primaryColor, enabled: true, width: 2, height: 30), + color: primaryColor, enabled: true, width: 2, height: 23), pinLength: 6, decoration: BoxLooseDecoration( strokeColorBuilder: @@ -82,8 +82,8 @@ class _StaffPinEditorState extends State { const SizedBox(height: 8), PinInputTextField( pinLength: 6, - cursor: Cursor( - color: primaryColor, enabled: true, width: 2, height: 30), + cursor: Cursor( + color: primaryColor, enabled: true, width: 2, height: 23), decoration: BoxLooseDecoration( strokeColorBuilder: PinListenColorBuilder(primaryColor, Colors.grey.shade400)),