diff --git a/lib/app.dart b/lib/app.dart index 0518ba7..ca88efd 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -36,7 +36,7 @@ class App extends StatefulWidget { final String title; const App({super.key, required this.title}); - @override + @override _AppState createState() => _AppState(); } diff --git a/lib/pages/carton/carton_cargo_table_old.dart b/lib/pages/carton/carton_cargo_table_old.dart deleted file mode 100644 index 1c3a6d5..0000000 --- a/lib/pages/carton/carton_cargo_table_old.dart +++ /dev/null @@ -1,181 +0,0 @@ -import 'package:fcs/domain/entities/cargo_type.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 'total_weight_edit.dart'; - -typedef OnAdd(CargoType cargoType); -typedef OnRemove(CargoType cargoType); - -class CargoTable extends StatefulWidget { - final List? cargoTypes; - final OnAdd? onAdd; - final OnRemove? onRemove; - - const CargoTable({Key? key, this.cargoTypes, this.onAdd, this.onRemove}) - : super(key: key); - - @override - _CargoTableState createState() => _CargoTableState(); -} - -class _CargoTableState extends State { - double totalWeight = 0; - List _cargos = []; - double remainingWeight = 0; - @override - Widget build(BuildContext context) { - return DataTable( - headingRowHeight: 40, - showCheckboxColumn: false, - columns: [ - DataColumn( - label: LocalText( - context, - "cargo.type", - color: Colors.grey, - ), - ), - DataColumn( - label: Row( - children: [ - Container( - padding: EdgeInsets.only(left: 50), - child: LocalText( - context, - "cargo.weight", - color: Colors.grey, - ), - ), - ], - ), - ), - ], - rows: getCargoRows(context), - ); - } - - List getCargoRows(BuildContext context) { - if (widget.cargoTypes == null) { - return []; - } - List _list = []; - List _types = []; - double _total = 0; - - var rows = widget.cargoTypes!.map((c) { - _total += c.weight; - return DataRow( - onSelectChanged: (bool? selected) async {}, - cells: [ - DataCell(Row( - children: [ - new Text( - c.name ?? "", - style: textStyle, - ), - new Text( - c.qty == 0 ? "" : " x ${c.qty.toString()}", - style: TextStyle(color: Colors.grey), - ), - ], - )), - DataCell( - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text(c.weight.toStringAsFixed(2), style: textStyle), - widget.onRemove == null - ? SizedBox( - width: 50, - ) - : IconButton( - icon: Icon( - Icons.remove_circle, - color: primaryColor, - ), - onPressed: () { - if (widget.onRemove != null) widget.onRemove!(c); - }) - ], - ), - ), - ], - ); - }).toList(); - - var totalRow = DataRow( - onSelectChanged: (bool? selected) {}, - cells: [ - DataCell(Align( - alignment: Alignment.centerRight, - child: LocalText( - context, - "shipment.cargo.total", - color: Colors.black87, - fontWeight: FontWeight.bold, - ), - )), - DataCell( - Padding( - padding: const EdgeInsets.only(right: 40.0), - child: Align( - alignment: Alignment.centerRight, - child: InkWell( - onTap: () async { - double? _t = await Navigator.of(context).push( - CupertinoPageRoute( - builder: (context) => - TotalWeightEdit(totalWeight: totalWeight))); - if (_t == null) return; - setState(() { - totalWeight = _t; - this.remainingWeight = this.totalWeight - _total; - widget.cargoTypes!.forEach((c) { - this._cargos.add(c); - }); - this._cargos.forEach((c) { - _list.add(c.name!); - }); - widget.cargoTypes!.forEach((c) { - _types.add(c.name!); - }); - if (this._cargos.length == - widget.cargoTypes!.length - 1) { - _types.forEach((t) { - if (!_list.contains(t)) { - widget.cargoTypes!.forEach((c) { - if (c.name == t) { - c.weight = this.remainingWeight; - } - }); - } - }); - } - }); - }, - child: Container( - padding: const EdgeInsets.all(7.0), - decoration: BoxDecoration( - border: Border.all(color: Colors.grey), - borderRadius: BorderRadius.all(Radius.circular(5.0)), - ), - child: Text(totalWeight.toStringAsFixed(2), - style: TextStyle(fontWeight: FontWeight.bold)), - ), - )), - ), - ), - ], - ); - rows.add(totalRow); - return rows; - } - - double getRemainBalance(double total) { - double _r = this.totalWeight < total ? 0 : this.totalWeight - total; - return _r; - } -} diff --git a/lib/pages/carton/carton_list.dart b/lib/pages/carton/carton_list.dart index 544dba6..95d804b 100644 --- a/lib/pages/carton/carton_list.dart +++ b/lib/pages/carton/carton_list.dart @@ -8,6 +8,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import '../../domain/entities/carton.dart'; +import '../../pagination/paginator_listview.dart'; import 'carton_editor.dart'; import 'carton_list_row.dart'; @@ -18,42 +20,44 @@ class CartonList extends StatefulWidget { class _CartonListState extends State { bool _isLoading = false; - var _controller = ScrollController(); + int _selectedIndex = 1; @override void initState() { super.initState(); - _controller.addListener(() async { - if (_controller.position.pixels == _controller.position.maxScrollExtent) { - Provider.of(context, listen: false).loadMore(); - } - }); - Provider.of(context, listen: false).initData(); + _init(); } - @override - void dispose() { - super.dispose(); + _init() { + var model = context.read(); + _selectedIndex = model.selectedIndex; + model.loadPaginationBoxes(_selectedIndex); + if (mounted) { + setState(() {}); + } } @override Widget build(BuildContext context) { var boxModel = Provider.of(context); + final popupMenu = LocalPopupMenuButton( - popmenus: [ - LocalPopupMenu( - id: 1, - textKey: "box.popupmenu.active", - selected: boxModel.selectedIndex == 1), - LocalPopupMenu( - id: 2, - textKey: "box.popupmenu.delivered", - selected: boxModel.selectedIndex == 2) - ], - popupMenuCallback: (p) => this.setState(() { - boxModel.selectedIndex = p.id; - }), - ); + popmenus: [ + LocalPopupMenu( + id: 1, + textKey: "box.popupmenu.active", + selected: boxModel.selectedIndex == 1), + LocalPopupMenu( + id: 2, + textKey: "box.popupmenu.delivered", + selected: boxModel.selectedIndex == 2) + ], + popupMenuCallback: (p) { + setState(() { + _selectedIndex = p.id; + }); + context.read().onChanged(_selectedIndex); + }); return LocalProgress( inAsyncCall: _isLoading, child: DefaultTabController( @@ -78,43 +82,10 @@ class _CartonListState extends State { label: LocalText(context, "boxes.new", color: Colors.white), backgroundColor: primaryColor, ), - body: Column( - children: [ - Expanded( - child: RefreshIndicator( - child: new ListView.separated( - physics: AlwaysScrollableScrollPhysics(), - controller: _controller, - separatorBuilder: (context, index) => Divider( - color: Colors.black, - height: 1, - ), - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: boxModel.boxes.length, - itemBuilder: (BuildContext context, int index) { - return CartonListRow( - key: ValueKey(boxModel.boxes[index].id), - box: boxModel.boxes[index]); - }), - onRefresh: () => boxModel.refresh(), - ), - ), - boxModel.isLoading - ? Container( - padding: EdgeInsets.all(8), - color: primaryColor, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Loading...", - style: TextStyle(color: Colors.white)), - ], - ), - ) - : Container(), - ], - ), + body: PaginatorListView( + paginatorListener: boxModel.getBoxes!, + rowBuilder: (p) => CartonListRow(box: p), + color: primaryColor), ), ), ); diff --git a/lib/pages/carton/carton_mix_table.dart b/lib/pages/carton/carton_mix_table.dart deleted file mode 100644 index 6d2cee4..0000000 --- a/lib/pages/carton/carton_mix_table.dart +++ /dev/null @@ -1,89 +0,0 @@ -import 'package:fcs/domain/entities/carton.dart'; -import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/pages/widgets/local_text.dart'; -import 'package:fcs/pages/widgets/local_title.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -typedef OnSelect = Function(Carton carton, bool checked); - -class CartonMixTable extends StatelessWidget { - final List? cartons; - final OnSelect? onSelect; - - const CartonMixTable({Key? key, this.cartons, this.onSelect}) - : super(key: key); - - @override - Widget build(BuildContext context) { - final tableTitle = Container( - padding: EdgeInsets.only(right: 10.0, top: 20), - child: Row( - children: [ - Container( - width: 30, - ), - Expanded( - child: LocalText(context, 'box.mix.number', color: Colors.grey), - ), - LocalText(context, 'box.cargo.total', color: Colors.grey), - ], - ), - ); - - final rows = cartons == null - ? [Container()] - : cartons!.asMap().entries.map((p) { - return Container( - color: (p.value.isChecked ?? false) - ? Colors.grey.withOpacity(0.2) - : Colors.grey.shade50.withOpacity(0.2), - child: Container( - padding: EdgeInsets.only( - left: 0.0, right: 10.0, top: 3.0, bottom: 3.0), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: p.key == cartons!.length - 1 - ? Colors.white - : Colors.grey.shade300, - width: 1), - ), - ), - child: Row( - children: [ - Checkbox( - value: p.value.isChecked, - activeColor: primaryColor, - onChanged: (bool? check) { - if (onSelect != null) onSelect!(p.value, check!); - }), - Expanded( - child: new Text( - p.value.cartonNumber ?? "", - style: textStyle, - )), - new Text( - p.value.actualWeight.toString(), - style: textStyle, - ), - ], - ), - ), - ); - }).toList(); - - return Column( - children: [ - LocalTitle(textKey: "box.shipment.boxes"), - tableTitle, - Divider( - color: Colors.grey[400], - ), - Column( - children: rows, - ), - ], - ); - } -} diff --git a/lib/pages/carton/carton_row.dart b/lib/pages/carton/carton_row.dart index 970a3a2..a1319aa 100644 --- a/lib/pages/carton/carton_row.dart +++ b/lib/pages/carton/carton_row.dart @@ -1,6 +1,5 @@ import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/helpers/theme.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:intl/intl.dart'; diff --git a/lib/pages/carton/input_text_border.dart b/lib/pages/carton/input_text_border.dart deleted file mode 100644 index 4c2eff7..0000000 --- a/lib/pages/carton/input_text_border.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:flutter/material.dart'; - -typedef OnAdd(String value); - -class InputTextBorder extends StatelessWidget { - final OnAdd? onAdd; - final TextEditingController? controller; - - const InputTextBorder({Key? key, this.onAdd, this.controller}) - : super(key: key); - @override - Widget build(BuildContext context) { - return TextFormField( - textAlign: TextAlign.center, - controller: controller, - onChanged: (v) { - if (onAdd != null) onAdd!(v); - }, - keyboardType: TextInputType.number, - decoration: new InputDecoration( - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.grey), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.grey), - ), - ), - ); - } -} diff --git a/lib/pages/carton/model/carton_model.dart b/lib/pages/carton/model/carton_model.dart index 25a12e5..d2bc72b 100644 --- a/lib/pages/carton/model/carton_model.dart +++ b/lib/pages/carton/model/carton_model.dart @@ -4,62 +4,20 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fcs/data/services/services.dart'; import 'package:fcs/domain/constants.dart'; import 'package:fcs/domain/entities/carton.dart'; -import 'package:fcs/domain/vo/shipment_status.dart'; -import 'package:fcs/helpers/paginator.dart'; import 'package:fcs/pages/main/model/base_model.dart'; import 'package:fcs/pagination/paginator_listener.dart'; import 'package:logging/logging.dart'; class CartonModel extends BaseModel { - List _boxes = []; - PaginatorListener? cartonsByFilter; - final log = Logger('CartonModel'); - List get boxes => _selectedIndex == 1 - ? _boxes - : List.from(_delivered?.values ?? []); - Paginator? _delivered; - int _selectedIndex = 1; + PaginatorListener? cartonsByFilter; + PaginatorListener? getBoxes; + + int selectedIndex = 1; int _selectedIndexFilter = 1; bool isLoading = false; - StreamSubscription? listener; - StreamSubscription? cartonListener; - static List statusHistory = [ - ShipmentStatus(status: "Packed", date: DateTime(2020, 6, 1), done: true), - ShipmentStatus(status: "Shipped", date: DateTime(2020, 6, 5), done: false), - ShipmentStatus( - status: "Delivered", date: DateTime(2020, 6, 15), done: false) - ]; - - // List get completed { - // return boxes.where((e) => e.status == "Delivered").toList() - // ..sort((e1, e2) { - // return e2.packageNumber.compareTo(e1.packageNumber); - // }); - // } - - // List get processed { - // return boxes.where((e) => e.status == "Packed").toList() - // ..sort((e1, e2) { - // return e2.packageNumber.compareTo(e1.packageNumber); - // }); - // } - - // List get upcoming { - // return boxes - // .where((e) => - // e.status == "Packed" || - // // e.status == "Received" || - // e.status == "Shipped" || - // e.status == "Arrived") - // .toList() - // ..sort((e1, e2) { - // return e2.packageNumber.compareTo(e1.packageNumber); - // }); - // } - List cartonTypes = [ carton_from_packages, carton_from_cartons, @@ -74,10 +32,7 @@ class CartonModel extends BaseModel { carton_small_bag ]; - set selectedIndex(int index) { - _selectedIndex = index; - notifyListeners(); - } + int get selectedIndexFilter => _selectedIndexFilter; set selectedIndexFilter(int index) { _selectedIndexFilter = index; @@ -86,19 +41,6 @@ class CartonModel extends BaseModel { notifyListeners(); } - int get selectedIndex => _selectedIndex; - int get selectedIndexFilter => _selectedIndexFilter; - - initData() async { - _selectedIndex = 1; - _selectedIndexFilter = 1; - _loadBoxes(); - - if (_delivered != null) _delivered!.close(); - _delivered = _getDelivered(); - _delivered!.load(); - } - @override void privilegeChanged() { if (user != null || !user!.hasCarton()) { @@ -106,40 +48,54 @@ class CartonModel extends BaseModel { } } + void initUser(user) { + super.initUser(user); + } + + @override + logout() async { + getBoxes?.close(); + cartonsByFilter?.close(); + } + Future _initData() async { logout(); _selectedIndexFilter = 1; - _loadPaginationCartons( _selectedIndexFilter == 1 ? "carton_weight" : "user_name"); } - Future _loadBoxes() async { + onChanged(int index) { + selectedIndex = index; + loadPaginationBoxes(selectedIndex); + notifyListeners(); + } + + Future loadPaginationBoxes(int index) async { if (user == null || !user!.hasCarton()) return; - String path = "/$cartons_collection/"; - if (listener != null) listener!.cancel(); - _boxes = []; - try { - listener = FirebaseFirestore.instance - .collection("$path") - .where("status", - whereIn: [carton_packed_status, carton_shipped_status]) - .where("is_deleted", isEqualTo: false) - .orderBy("created_at", descending: true) - .snapshots() - .listen((QuerySnapshot snapshot) { - _boxes.clear(); - _boxes = snapshot.docs.map((documentSnapshot) { - var s = Carton.fromMap( - documentSnapshot.data() as Map, - documentSnapshot.id); - return s; - }).toList(); - notifyListeners(); - }); - } catch (e) { - log.warning("Error!! $e"); + + String path = "/$cartons_collection"; + Query col = FirebaseFirestore.instance.collection(path); + Query pageQuery = FirebaseFirestore.instance.collection(path); + + if (index == 1) { + col = col.where("status", + whereIn: [carton_packed_status, carton_shipped_status]); + pageQuery = pageQuery.where("status", + whereIn: [carton_packed_status, carton_shipped_status]); } + + if (index == 2) { + col = col.where("is_delivered", isEqualTo: true); + pageQuery = pageQuery.where("is_delivered", isEqualTo: true); + } + + pageQuery = pageQuery.orderBy("created_at", descending: true); + + getBoxes?.close(); + getBoxes = PaginatorListener( + col, pageQuery, (data, id) => Carton.fromMap(data, id), + rowPerLoad: 30); } _loadPaginationCartons(String orderName) { @@ -164,49 +120,6 @@ class CartonModel extends BaseModel { rowPerLoad: 30); } - Paginator? _getDelivered() { - if (user == null || !user!.hasCarton()) return null; - - var pageQuery = FirebaseFirestore.instance - .collection("/$cartons_collection") - .where("is_delivered", isEqualTo: true) - .where("is_deleted", isEqualTo: false); - var paginator = new Paginator(pageQuery, rowPerLoad: 20, toObj: (data, id) { - return Carton.fromMap(data, id); - }); - return paginator; - } - - Future loadMore() async { - if (_delivered == null && _delivered!.ended || selectedIndex == 1) return; - isLoading = true; - notifyListeners(); - await _delivered!.load(onFinished: () { - isLoading = false; - notifyListeners(); - }); - } - - Future refresh() async { - if (selectedIndex == 1) return; - await _delivered?.refresh(onFinished: () { - notifyListeners(); - }); - } - - void initUser(user) { - super.initUser(user); - } - - @override - logout() async { - if (listener != null) await listener!.cancel(); - if (cartonListener != null) await cartonListener!.cancel(); - if (_delivered != null) _delivered!.close(); - if (cartonsByFilter != null) cartonsByFilter!.close(); - _boxes = []; - } - Future> getCartons(String shipmentID) async { String path = "/$cartons_collection"; var querySnap = await FirebaseFirestore.instance diff --git a/lib/pages/carton/total_weight_edit.dart b/lib/pages/carton/total_weight_edit.dart deleted file mode 100644 index da2b242..0000000 --- a/lib/pages/carton/total_weight_edit.dart +++ /dev/null @@ -1,86 +0,0 @@ -import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/pages/widgets/input_text.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:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:fcs/pages/main/util.dart'; - -typedef void ProfileCallback(); - -class TotalWeightEdit extends StatefulWidget { - final double? totalWeight; - - const TotalWeightEdit({Key? key, this.totalWeight}) : super(key: key); - @override - _TotalWeightEditState createState() => _TotalWeightEditState(); -} - -class _TotalWeightEditState extends State { - final TextEditingController totalController = new TextEditingController(); - bool _loading = false; - - @override - void initState() { - super.initState(); - totalController.text = widget.totalWeight!.toStringAsFixed(2); - } - - @override - Widget build(BuildContext context) { - final totalInputBox = InputText( - labelTextKey: 'shipment.cargo.total', - iconData: FontAwesomeIcons.weightHanging, - textInputType: TextInputType.number, - controller: totalController); - - final saveBtn = - fcsButton(context, getLocalString(context, "btn.save"), callack: _save); - - return LocalProgress( - inAsyncCall: _loading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - title: LocalText( - context, - "box.cargo_total_title", - fontSize: 20, - color: primaryColor, - ), - backgroundColor: Colors.white, - shadowColor: Colors.transparent, - leading: IconButton( - icon: Icon( - CupertinoIcons.back, - size: 35, - color: primaryColor, - ), - onPressed: () => Navigator.of(context).pop(), - ), - ), - body: ListView( - padding: EdgeInsets.all(18), - children: [totalInputBox, SizedBox(height: 30), saveBtn], - ), - ), - ); - } - - _save() async { - setState(() { - _loading = true; - }); - try { - double total = double.parse(totalController.text); - Navigator.pop(context, total); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _loading = false; - }); - } - } -} diff --git a/lib/pages/customer/customer_list.dart b/lib/pages/customer/customer_list.dart index 24981aa..e57e97e 100644 --- a/lib/pages/customer/customer_list.dart +++ b/lib/pages/customer/customer_list.dart @@ -15,6 +15,7 @@ import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:share/share.dart'; +import '../../pagination/paginator_listview.dart'; import 'invitation_create.dart'; class CustomerList extends StatefulWidget { @@ -27,6 +28,13 @@ class _CustomerListState extends State { final double dotSize = 15.0; bool _isLoading = false; + + @override + void initState() { + context.read().loadPaginationCustomers(); + super.initState(); + } + @override Widget build(BuildContext context) { var customerModel = Provider.of(context); @@ -34,55 +42,40 @@ class _CustomerListState extends State { return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(CupertinoIcons.back), - onPressed: () => Navigator.of(context).pop(), - ), - actions: [ - IconButton( - icon: Icon(Icons.search, color: Colors.white), - onPressed: () => searchUser(context, onUserSelect: (u) { - _select(u); - })), - ], - backgroundColor: primaryColor, - title: LocalText( - context, - "customer.list.title", - fontSize: 20, - color: Colors.white, - ), - ), - floatingActionButton: FloatingActionButton.extended( - onPressed: () { - Navigator.of(context).push( - CupertinoPageRoute(builder: (context) => InvitationCreate())); - }, - icon: Icon(Icons.add), - label: LocalText(context, "invitation.new", color: Colors.white), - backgroundColor: primaryColor, - ), - body: Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.grey, - ), - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: customerModel.customers.length, - itemBuilder: (BuildContext context, int index) { - User customer = customerModel.customers[index]; - return _item(customer); - }), + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), ), - ], - ), - ), + actions: [ + IconButton( + icon: Icon(Icons.search, color: Colors.white), + onPressed: () => searchUser(context, onUserSelect: (u) { + _select(u); + })), + ], + backgroundColor: primaryColor, + title: LocalText( + context, + "customer.list.title", + fontSize: 20, + color: Colors.white, + ), + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () { + Navigator.of(context).push( + CupertinoPageRoute(builder: (context) => InvitationCreate())); + }, + icon: Icon(Icons.add), + label: LocalText(context, "invitation.new", color: Colors.white), + backgroundColor: primaryColor, + ), + body: PaginatorListView( + paginatorListener: customerModel.getCustomers!, + rowBuilder: (p) => _item(p), + color: primaryColor)), ); } diff --git a/lib/pages/customer/invitation_editor.dart b/lib/pages/customer/invitation_editor.dart deleted file mode 100644 index fe2f946..0000000 --- a/lib/pages/customer/invitation_editor.dart +++ /dev/null @@ -1,101 +0,0 @@ -import 'package:fcs/domain/entities/user.dart'; -import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/pages/customer/model/customer_model.dart'; -import 'package:fcs/pages/main/util.dart'; -import 'package:fcs/pages/widgets/display_text.dart'; -import 'package:fcs/pages/widgets/progress.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; - -typedef void FindCallBack(); - -class InvitationEditor extends StatefulWidget { - final User? customer; - const InvitationEditor({this.customer}); - @override - _InvitationEditorState createState() => _InvitationEditorState(); -} - -class _InvitationEditorState extends State { - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var phoneNumberBox = Row( - children: [ - Expanded( - child: DisplayText( - text: widget.customer!.phoneNumber, - labelTextKey: getLocalString(context, "customer.phone"), - iconData: Icons.phone, - )), - IconButton( - icon: Icon(Icons.open_in_new, color: primaryColor), - onPressed: () => call(context, widget.customer?.phoneNumber ?? "")), - ], - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: Colors.white, - shadowColor: Colors.transparent, - centerTitle: true, - leading: new IconButton( - icon: new Icon( - CupertinoIcons.back, - color: primaryColor, - size: 30, - ), - onPressed: () => Navigator.of(context).pop(), - ), - title: Text( - widget.customer?.name ?? "", - style: TextStyle(fontSize: 20, color: primaryColor), - ), - ), - body: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - children: [ - Expanded( - child: ListView( - children: [phoneNumberBox], - ), - ), - fcsButton(context, getLocalString(context, "btn.delete"), - callack: _delete) - ], - ), - ), - )); - } - - _delete() async { - showConfirmDialog(context, "invitation.confirm.delete", () async { - setState(() { - _isLoading = true; - }); - if (widget.customer == null) return; - CustomerModel customerModel = - Provider.of(context, listen: false); - try { - await customerModel.deleteInvite(widget.customer?.phoneNumber ?? ""); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - }); - } -} diff --git a/lib/pages/customer/model/customer_model.dart b/lib/pages/customer/model/customer_model.dart index 149e9d1..c2f0acf 100644 --- a/lib/pages/customer/model/customer_model.dart +++ b/lib/pages/customer/model/customer_model.dart @@ -13,89 +13,28 @@ class CustomerModel extends BaseModel { final log = Logger('CustomerModel'); PaginatorListener? getCustomers; - List customers = []; - List invitations = []; - StreamSubscription? customerListener; - StreamSubscription? invitationListener; - - @override - void privilegeChanged() { - super.privilegeChanged(); - _loadCustomer(); - _loadInvitations(); - } - @override logout() async { - if (customerListener != null) customerListener!.cancel(); - if (invitationListener != null) invitationListener!.cancel(); - customers = []; - invitations = []; getCustomers?.close(); } - - - Future inviteUser(String userName, String phoneNumber) { - return Services.instance.userService.inviteUser(userName, phoneNumber); - } - - Future deleteInvite(String phoneNumber) { - return Services.instance.userService.deleteInvite(phoneNumber); - } - - Future acceptRequest(String userID) { - return Services.instance.userService.acceptRequest(userID); - } - - Future _loadCustomer() async { + loadPaginationCustomers() { if (user == null && !user!.hasCustomers()) return; - try { - if (customerListener != null) customerListener!.cancel(); + String path = "/$user_collection"; + Query col = FirebaseFirestore.instance + .collection(path) + .where("is_sys_admin", isEqualTo: false); - customerListener = FirebaseFirestore.instance - .collection("/$user_collection") - .where("is_sys_admin", isEqualTo: false) - .orderBy("message_time", descending: true) - .snapshots() - .listen((QuerySnapshot snapshot) { - customers.clear(); - customers = snapshot.docs.map((documentSnapshot) { - var user = User.fromMap( - documentSnapshot.data() as Map, - documentSnapshot.id); - return user; - }).toList(); - notifyListeners(); - }); - } catch (e) { - log.warning("error:$e"); - } - } + Query pageQuery = FirebaseFirestore.instance + .collection(path) + .where("is_sys_admin", isEqualTo: false) + .orderBy("message_time", descending: true); - Future _loadInvitations() async { - if (user == null && !user!.hasCustomers()) return; - - try { - if (invitationListener != null) invitationListener!.cancel(); - - invitationListener = FirebaseFirestore.instance - .collection("/$invitations_collection") - .snapshots() - .listen((QuerySnapshot snapshot) { - invitations.clear(); - invitations = snapshot.docs.map((documentSnapshot) { - var user = User.fromMap( - documentSnapshot.data() as Map, - documentSnapshot.id); - return user; - }).toList(); - notifyListeners(); - }); - } catch (e) { - log.warning("error:$e"); - } + getCustomers?.close(); + getCustomers = PaginatorListener( + col, pageQuery, (data, id) => User.fromMap(data, id), + rowPerLoad: 30); } Future getUser(String? id) async { @@ -125,4 +64,16 @@ class CustomerModel extends BaseModel { Future enableUser(User user, bool enabled) { return Services.instance.userService.enableUser(user.id ?? "", enabled); } + + Future inviteUser(String userName, String phoneNumber) { + return Services.instance.userService.inviteUser(userName, phoneNumber); + } + + Future deleteInvite(String phoneNumber) { + return Services.instance.userService.deleteInvite(phoneNumber); + } + + Future acceptRequest(String userID) { + return Services.instance.userService.acceptRequest(userID); + } } diff --git a/lib/pages/delivery/delivery_info.dart b/lib/pages/delivery/delivery_info.dart index 149a133..9caff26 100644 --- a/lib/pages/delivery/delivery_info.dart +++ b/lib/pages/delivery/delivery_info.dart @@ -107,9 +107,9 @@ class _DeliveryInfoState extends State { } _calShipmentWeight() { - double l = double.parse(_lengthController.text); - double w = double.parse(_widthController.text); - double h = double.parse(_heightController.text); + double l = double.tryParse(_lengthController.text) ?? 0; + double w = double.tryParse(_widthController.text) ?? 0; + double h = double.tryParse(_heightController.text) ?? 0; setState(() { shipmentWeight = l * w * h / volumetricRatio; }); diff --git a/lib/pages/delivery/delivery_list.dart b/lib/pages/delivery/delivery_list.dart index 2e148b7..01dfbca 100644 --- a/lib/pages/delivery/delivery_list.dart +++ b/lib/pages/delivery/delivery_list.dart @@ -7,6 +7,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import '../../domain/entities/carton.dart'; +import '../../pagination/paginator_listview.dart'; import 'delivery_list_row.dart'; import 'model/delivery_model.dart'; @@ -17,97 +19,62 @@ class DeliverList extends StatefulWidget { class _DeliverListState extends State { bool _isLoading = false; - var _controller = ScrollController(); + int _selectedIndex = 1; @override void initState() { super.initState(); - _controller.addListener(() async { - if (_controller.position.pixels == _controller.position.maxScrollExtent) { - Provider.of(context, listen: false).loadMore(); - } - }); - Provider.of(context, listen: false).initData(); + _init(); } - @override - void dispose() { - super.dispose(); + _init() { + var model = context.read(); + _selectedIndex = model.selectedIndex; + model.loadPaginationCartons(_selectedIndex); + if (mounted) { + setState(() {}); + } } @override Widget build(BuildContext context) { var deliveryModel = Provider.of(context); + final popupMenu = LocalPopupMenuButton( - popmenus: [ - LocalPopupMenu( - id: 1, - textKey: "delivery.popupmenu.active", - selected: deliveryModel.selectedIndex == 1), - LocalPopupMenu( - id: 2, - textKey: "delivery.popupmenu.delivered", - selected: deliveryModel.selectedIndex == 2) - ], - popupMenuCallback: (p) => this.setState(() { - deliveryModel.selectedIndex = p.id; - }), - ); + popmenus: [ + LocalPopupMenu( + id: 1, + textKey: "delivery.popupmenu.active", + selected: deliveryModel.selectedIndex == 1), + LocalPopupMenu( + id: 2, + textKey: "delivery.popupmenu.delivered", + selected: deliveryModel.selectedIndex == 2) + ], + popupMenuCallback: (p) { + setState(() { + _selectedIndex = p.id; + }); + context.read().onChanged(_selectedIndex); + }); + return LocalProgress( - inAsyncCall: _isLoading, - child: DefaultTabController( - length: 2, + inAsyncCall: _isLoading, child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(CupertinoIcons.back), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: LocalText(context, "delivery", - color: Colors.white, fontSize: 20), - actions: [popupMenu], - ), - body: Column( - children: [ - Expanded( - child: RefreshIndicator( - child: new ListView.separated( - physics: AlwaysScrollableScrollPhysics(), - controller: _controller, - separatorBuilder: (context, index) => Divider( - color: Colors.black, - height: 1, - ), - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: deliveryModel.cartons.length, - itemBuilder: (BuildContext context, int index) { - return DeliveryListRow( - key: ValueKey(deliveryModel.cartons[index].id), - box: deliveryModel.cartons[index]); - }), - onRefresh: () => deliveryModel.refresh(), - ), + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), ), - deliveryModel.isLoading - ? Container( - padding: EdgeInsets.all(8), - color: primaryColor, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Loading...", - style: TextStyle(color: Colors.white)), - ], - ), - ) - : Container(), - ], - ), - ), - ), - ); + backgroundColor: primaryColor, + title: LocalText(context, "delivery", + color: Colors.white, fontSize: 20), + actions: [popupMenu], + ), + body: PaginatorListView( + paginatorListener: deliveryModel.getCartons!, + rowBuilder: (p) => DeliveryListRow(box: p), + color: primaryColor))); } } diff --git a/lib/pages/delivery/model/delivery_model.dart b/lib/pages/delivery/model/delivery_model.dart index 97da1e9..e8563a5 100644 --- a/lib/pages/delivery/model/delivery_model.dart +++ b/lib/pages/delivery/model/delivery_model.dart @@ -4,100 +4,61 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fcs/data/services/services.dart'; import 'package:fcs/domain/constants.dart'; import 'package:fcs/domain/entities/carton.dart'; -import 'package:fcs/helpers/paginator.dart'; import 'package:fcs/pages/main/model/base_model.dart'; import 'package:logging/logging.dart'; +import '../../../pagination/paginator_listener.dart'; + class DeliveryModel extends BaseModel { final log = Logger('DeliveryModel'); - List get cartons => _selectedIndex == 1 - ? _cartons - : List.from(_delivered?.values ?? []); + PaginatorListener? getCartons; + int selectedIndex = 1; - Paginator? _delivered; - int _selectedIndex = 1; - bool isLoading = false; - List _cartons = []; - StreamSubscription? listener; - - set selectedIndex(int index) { - _selectedIndex = index; + onChanged(int index) { + selectedIndex = index; + loadPaginationCartons(selectedIndex); notifyListeners(); } - int get selectedIndex => _selectedIndex; - - initData() { - _selectedIndex = 1; - _loadCartons(); - - if (_delivered != null) _delivered!.close(); - _delivered = _getDelivered(); - _delivered!.load(); - } - - Future _loadCartons() async { + loadPaginationCartons(int index) { if (user == null || !user!.hasDeliveries()) return; - String path = "/$cartons_collection/"; - if (listener != null) listener!.cancel(); - _cartons = []; - try { - listener = FirebaseFirestore.instance - .collection("$path") + String path = "/$cartons_collection"; + + Query col = FirebaseFirestore.instance.collection(path); + Query pageQuery = FirebaseFirestore.instance.collection(path); + + if (index == 1) { + col = col .where("status", isEqualTo: carton_shipped_status) .where("carton_type", whereIn: [ - carton_from_packages, - carton_from_shipments, - carton_small_bag - ]) - .where("is_deleted", isEqualTo: false) - .orderBy("carton_number", descending: false) - .snapshots() - .listen((QuerySnapshot snapshot) { - _cartons.clear(); - _cartons = snapshot.docs.map((documentSnapshot) { - var s = Carton.fromMap( - documentSnapshot.data as Map, - documentSnapshot.id); - return s; - }).toList(); - notifyListeners(); - }); - } catch (e) { - log.warning("Error!! $e"); + carton_from_packages, + carton_from_shipments, + carton_small_bag + ]); + pageQuery = pageQuery + .where("status", isEqualTo: carton_shipped_status) + .where("carton_type", whereIn: [ + carton_from_packages, + carton_from_shipments, + carton_small_bag + ]); } - } - Paginator _getDelivered() { - if (user == null || !user!.hasDeliveries()) throw "No Privilege"; + if (index == 2) { + col = col + .where("is_delivered", isEqualTo: true) + .where("status", whereIn: [carton_delivered_status]); + pageQuery = pageQuery + .where("is_delivered", isEqualTo: true) + .where("status", whereIn: [carton_delivered_status]); + } - var pageQuery = FirebaseFirestore.instance - .collection("/$cartons_collection") - .where("is_delivered", isEqualTo: true) - .where("status", whereIn: [carton_delivered_status]).where("is_deleted", - isEqualTo: false); - var paginator = new Paginator(pageQuery, rowPerLoad: 20, toObj: (data, id) { - return Carton.fromMap(data, id); - }); - return paginator; - } + pageQuery = pageQuery.orderBy("carton_number"); - Future loadMore() async { - if (_delivered!.ended || _selectedIndex == 1) return; - isLoading = true; - notifyListeners(); - await _delivered!.load(onFinished: () { - isLoading = false; - notifyListeners(); - }); - } - - Future refresh() async { - if (_selectedIndex == 1) return; - - await _delivered!.refresh(onFinished: () { - notifyListeners(); - }); + getCartons?.close(); + getCartons = PaginatorListener( + col, pageQuery, (data, id) => Carton.fromMap(data, id), + rowPerLoad: 30); } void initUser(user) { @@ -106,9 +67,7 @@ class DeliveryModel extends BaseModel { @override logout() async { - if (listener != null) await listener!.cancel(); - if (_delivered != null) _delivered!.close(); - _cartons = []; + getCartons?.close(); } Future deliver(Carton carton) { diff --git a/lib/pages/fcs_shipment/fcs_shipment_list.dart b/lib/pages/fcs_shipment/fcs_shipment_list.dart index a4a632c..ba1c60e 100644 --- a/lib/pages/fcs_shipment/fcs_shipment_list.dart +++ b/lib/pages/fcs_shipment/fcs_shipment_list.dart @@ -4,10 +4,12 @@ import 'package:fcs/pages/widgets/local_popup_menu_button.dart'; import 'package:fcs/pages/widgets/local_popupmenu.dart'; import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/progress.dart'; +import 'package:fcs/pagination/paginator_listview.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import '../../domain/entities/fcs_shipment.dart'; import 'fcs_shipment_editor.dart'; import 'fcs_shipment_list_row.dart'; @@ -18,18 +20,21 @@ class FcsShipmentList extends StatefulWidget { class _FcsShipmentListState extends State { bool _isLoading = false; - var _controller = ScrollController(); + int _selectedIndex = 1; @override void initState() { super.initState(); + _init(); + } - _controller.addListener(() async { - if (_controller.position.pixels == _controller.position.maxScrollExtent) { - Provider.of(context, listen: false).loadMore(); - } - }); - Provider.of(context, listen: false).initData(); + _init() { + var model = context.read(); + _selectedIndex = model.selectedIndex; + model.loadFcsShipments(_selectedIndex); + if (mounted) { + setState(() {}); + } } @override @@ -47,9 +52,12 @@ class _FcsShipmentListState extends State { textKey: "FCSshipment.popupmenu.shipped", selected: shipmentModel.selectedIndex == 2) ], - popupMenuCallback: (p) => this.setState(() { - shipmentModel.selectedIndex = p.id; - }), + popupMenuCallback: (p) { + setState(() { + _selectedIndex = p.id; + }); + context.read().onChanged(_selectedIndex); + }, ); return LocalProgress( @@ -67,51 +75,17 @@ class _FcsShipmentListState extends State { actions: [popupMenu], ), floatingActionButton: FloatingActionButton.extended( - onPressed: () { - _newShipment(); - }, - icon: Icon(Icons.add), - label: LocalText(context, "FCSshipment.add", color: Colors.white), - backgroundColor: primaryColor, - ), - body: Column( - children: [ - Expanded( - child: RefreshIndicator( - child: ListView.separated( - physics: AlwaysScrollableScrollPhysics(), - controller: _controller, - separatorBuilder: (context, index) => Divider( - color: Colors.black, - height: 1, - ), - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: shipmentModel.fcsShipments.length, - itemBuilder: (BuildContext context, int index) { - return FcsShipmentListRow( - key: ValueKey( - shipmentModel.fcsShipments[index].id), - shipment: shipmentModel.fcsShipments[index]); - }), - onRefresh: () => shipmentModel.refresh(), - ), - ), - shipmentModel.isLoading - ? Container( - padding: EdgeInsets.all(8), - color: primaryColor, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Loading...", - style: TextStyle(color: Colors.white)), - ], - ), - ) - : Container(), - ], - ))); + onPressed: () { + _newShipment(); + }, + icon: Icon(Icons.add), + label: + LocalText(context, "FCSshipment.add", color: Colors.white), + backgroundColor: primaryColor), + body: PaginatorListView( + paginatorListener: shipmentModel.fcsShipments!, + rowBuilder: (p) => FcsShipmentListRow(shipment: p), + color: primaryColor))); } _newShipment() { diff --git a/lib/pages/fcs_shipment/model/fcs_shipment_model.dart b/lib/pages/fcs_shipment/model/fcs_shipment_model.dart index 8e0d983..18b92a8 100644 --- a/lib/pages/fcs_shipment/model/fcs_shipment_model.dart +++ b/lib/pages/fcs_shipment/model/fcs_shipment_model.dart @@ -4,100 +4,48 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fcs/data/services/services.dart'; import 'package:fcs/domain/constants.dart'; import 'package:fcs/domain/entities/fcs_shipment.dart'; -import 'package:fcs/helpers/paginator.dart'; import 'package:fcs/pages/main/model/base_model.dart'; import 'package:logging/logging.dart'; +import '../../../pagination/paginator_listener.dart'; + class FcsShipmentModel extends BaseModel { final log = Logger('FcsShipmentModel'); - - StreamSubscription? listener; - List _fcsShipments = []; - List get fcsShipments => _selectedIndex == 1 - ? _fcsShipments - : List.from(_shipped!.values); - - Paginator? _shipped; + PaginatorListener? fcsShipments; bool isLoading = false; - int _selectedIndex = 1; - set selectedIndex(int index) { - _selectedIndex = index; + int selectedIndex = 1; + + onChanged(int index) { + selectedIndex = index; + loadFcsShipments(selectedIndex); notifyListeners(); } - int get selectedIndex => _selectedIndex; - - @override - void privilegeChanged() { - super.privilegeChanged(); - _loadFcsShipments(); - } - - initData() { - _selectedIndex = 1; - _loadFcsShipments(); - - if (_shipped != null) _shipped!.close(); - _shipped = _getShipped(); - _shipped!.load(); - } - - Future _loadFcsShipments() async { + loadFcsShipments(int index) { if (user == null || !user!.hasFcsShipments()) return; - String path = "/$fcs_shipment_collection/"; - if (listener != null) listener!.cancel(); - _fcsShipments = []; - try { - listener = FirebaseFirestore.instance - .collection("$path") - .where("status", isEqualTo: fcs_shipment_confirmed_status) - .where("is_deleted", isEqualTo: false) - .orderBy("shipment_number", descending: true) - .snapshots() - .listen((QuerySnapshot snapshot) { - _fcsShipments.clear(); - _fcsShipments = snapshot.docs.map((documentSnapshot) { - var s = FcsShipment.fromMap( - documentSnapshot.data() as Map, - documentSnapshot.id); - return s; - }).toList(); - notifyListeners(); - }); - } catch (e) { - log.warning("Error!! $e"); + + String path = "/$fcs_shipment_collection"; + Query col = FirebaseFirestore.instance.collection(path); + Query pageQuery = FirebaseFirestore.instance.collection(path); + + if (index == 1) { + col = col.where("status", isEqualTo: fcs_shipment_confirmed_status); + pageQuery = + pageQuery.where("status", isEqualTo: fcs_shipment_confirmed_status); } - } - Paginator _getShipped() { - if (user == null || !user!.hasFcsShipments()) throw "No Privilege"; + if (index == 2) { + col = col.where("status", isEqualTo: fcs_shipment_shipped_status); + pageQuery = + pageQuery.where("status", isEqualTo: fcs_shipment_shipped_status); + } - var pageQuery = FirebaseFirestore.instance - .collection("/$fcs_shipment_collection") - .where("status", isEqualTo: fcs_shipment_shipped_status) - .where("is_deleted", isEqualTo: false) - .orderBy("shipment_number", descending: true); - var paginator = new Paginator(pageQuery, rowPerLoad: 20, toObj: (data, id) { - return FcsShipment.fromMap(data, id); - }); - return paginator; - } + pageQuery = pageQuery.orderBy("shipment_number", descending: true); - Future loadMore() async { - if (_shipped!.ended || _selectedIndex == 1) return; - isLoading = true; - notifyListeners(); - await _shipped!.load(onFinished: () { - isLoading = false; - notifyListeners(); - }); - } - - Future refresh() async { - if (_selectedIndex == 1) return; - await _shipped!.refresh(onFinished: () { - notifyListeners(); - }); + fcsShipments?.close(); + fcsShipments = PaginatorListener( + col, pageQuery, (data, id) => FcsShipment.fromMap(data, id), + rowPerLoad: 30); } Future> getActiveFcsShipments() async { @@ -157,9 +105,7 @@ class FcsShipmentModel extends BaseModel { @override logout() async { - if (listener != null) await listener!.cancel(); - if (_shipped != null) _shipped!.close(); - _fcsShipments = []; + fcsShipments?.close(); } Future create(FcsShipment fcsShipment) { diff --git a/lib/pages/invoice/box_addition.dart b/lib/pages/invoice/box_addition.dart deleted file mode 100644 index 1a78001..0000000 --- a/lib/pages/invoice/box_addition.dart +++ /dev/null @@ -1,102 +0,0 @@ -import 'package:fcs/domain/entities/carton.dart'; -import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/localization/app_translations.dart'; -import 'package:fcs/pages/widgets/progress.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -class BoxAddition extends StatefulWidget { - final Carton? box; - BoxAddition({this.box}); - - @override - _BoxAdditionState createState() => _BoxAdditionState(); -} - -class _BoxAdditionState extends State { - bool _isLoading = false; - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(CupertinoIcons.back), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context)!.text("box.edit.title")), - ), - body: Card( - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(10.0), - child: ListView(children: [ - DropdownButtonFormField( - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Box Number', - icon: Icon(Icons.pages)), - items: [], - // boxModel.processed - // .map((e) => DropdownMenuItem( - // child: Text( - // '${e.shipmentNumber}-${e.receiverNumber} #${e.boxNumber}'), - // value: e)) - // .toList(), - onChanged: (map) => {}, - ), - ]), - )), - widget.box == null - ? Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: TextButton( - style: TextButton.styleFrom( - backgroundColor: primaryColor), - child: Text( - 'Add box', - style: TextStyle(color: Colors.white), - ), - // color: primaryColor, - // textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - : Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: TextButton( - style: TextButton.styleFrom( - backgroundColor: primaryColor), - child: Text('Save box', - style: TextStyle(color: Colors.white)), - // color: primaryColor, - // textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))), - SizedBox( - height: 30, - ) - ], - ), - ), - ), - ); - } -} diff --git a/lib/pages/main/home_page.dart b/lib/pages/main/home_page.dart index 8cfe636..85124a5 100644 --- a/lib/pages/main/home_page.dart +++ b/lib/pages/main/home_page.dart @@ -400,7 +400,7 @@ class _HomePageState extends State { Navigator.of(context).push(RightLeftPageRoute(Profile())); }, iconSize: 30, - icon: Icon(Icons.account_circle), + icon: Icon(Icons.account_circle,color: buttonColor,), ); var searchInput = Row(children: [ diff --git a/lib/pages/package/model/package_model.dart b/lib/pages/package/model/package_model.dart index 9d57ab4..0f50b04 100644 --- a/lib/pages/package/model/package_model.dart +++ b/lib/pages/package/model/package_model.dart @@ -42,7 +42,6 @@ class PackageModel extends BaseModel { Future _initData() async { _menuSelectedIndex = 1; - _loadPaginationPackages(_menuSelectedIndex == 2); _loadPaginationCustomerPackages(_menuSelectedIndex == 2); _loadPaginationActivePackages(); diff --git a/lib/pages/pickup/model/pickup_model.dart b/lib/pages/pickup/model/pickup_model.dart index 69663e4..58f072a 100644 --- a/lib/pages/pickup/model/pickup_model.dart +++ b/lib/pages/pickup/model/pickup_model.dart @@ -13,29 +13,18 @@ import 'package:path/path.dart' as Path; class PickupModel extends BaseModel { final log = Logger('PickupModel'); - PaginatorListener? pickups; void initUser(user) { super.initUser(user); } - void privilegeChanged() { - if (user != null) { - _initData(); - } - } - - Future _initData() async { - _loadPaginationPickups(); - } - @override logout() async { if (pickups != null) pickups!.close(); } - _loadPaginationPickups() { + loadPaginationPickups() { if (user == null) return; String path = "/$pickup_collection"; Query col = FirebaseFirestore.instance.collection(path); diff --git a/lib/pages/pickup/pickup_list.dart b/lib/pages/pickup/pickup_list.dart index 7556142..2bf4b76 100644 --- a/lib/pages/pickup/pickup_list.dart +++ b/lib/pages/pickup/pickup_list.dart @@ -22,13 +22,10 @@ class _PickupListState extends State { @override void initState() { + context.read().loadPaginationPickups(); super.initState(); } - @override - void dispose() { - super.dispose(); - } @override Widget build(BuildContext context) { diff --git a/lib/pages/processing_old/processing_editor.dart b/lib/pages/processing_old/processing_editor.dart deleted file mode 100644 index 649441f..0000000 --- a/lib/pages/processing_old/processing_editor.dart +++ /dev/null @@ -1,256 +0,0 @@ -import 'package:fcs/domain/entities/market.dart'; -import 'package:fcs/domain/entities/package.dart'; -import 'package:fcs/domain/entities/user.dart'; -import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/pages/market/market_editor.dart'; -import 'package:fcs/pages/market/model/market_model.dart'; -import 'package:fcs/pages/package/model/package_model.dart'; -import 'package:fcs/pages/package/tracking_id_page.dart'; -import 'package:fcs/pages/main/util.dart'; -import 'package:fcs/pages/user_search/user_serach.dart'; -import 'package:fcs/pages/widgets/display_text.dart'; -import 'package:fcs/pages/widgets/fcs_id_icon.dart'; -import 'package:fcs/pages/widgets/input_text.dart'; -import 'package:fcs/pages/widgets/local_text.dart'; -import 'package:fcs/pages/widgets/multi_img_controller.dart'; -import 'package:fcs/pages/widgets/multi_img_file.dart'; -import 'package:fcs/pages/widgets/progress.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_icons_null_safety/flutter_icons_null_safety.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; - -class ProcessingEditor extends StatefulWidget { - final Package? package; - ProcessingEditor({this.package}); - - @override - _ProcessingEditorState createState() => _ProcessingEditorState(); -} - -class _ProcessingEditorState extends State { - TextEditingController _remarkCtl = new TextEditingController(); - TextEditingController _descCtl = new TextEditingController(); - - Package? _package; - User? _user; - bool _isLoading = false; - - @override - void initState() { - super.initState(); - _package = widget.package; - selectedMarket = _package!.market ?? ""; - _descCtl.text = _package!.desc!; - _remarkCtl.text = _package!.remark!; - multiImgController.setImageUrls = _package!.photoUrls; - _user = User( - fcsID: _package!.fcsID ?? "", - name: _package!.userName ?? "", - phoneNumber: _package!.phoneNumber ?? ""); - } - - final DateFormat dateFormat = DateFormat("d MMM yyyy"); - - bool isNew = false; - MultiImgController multiImgController = MultiImgController(); - - @override - Widget build(BuildContext context) { - var fcsIDBox = Row( - children: [ - Expanded( - child: DisplayText( - text: _user!.fcsID??"", - labelTextKey: "processing.fcs.id", - icon: FcsIDIcon(), - )), - IconButton( - icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, onUserSelect: (u) { - setState(() { - this._user = u; - }); - })), - ], - ); - final namebox = DisplayText( - text: _user!.name??"", - labelTextKey: "processing.name", - iconData: Icons.person, - ); - final phoneNumberBox = DisplayText( - text: _user!.phoneNumber??"", - labelTextKey: "processing.phone", - iconData: Icons.phone, - ); - - final trackingIdBox = DisplayText( - text: _package!.trackingID??"", - labelTextKey: "processing.tracking.id", - iconData: MaterialCommunityIcons.barcode_scan, - ); - final completeProcessingBtn = fcsButton( - context, - getLocalString(context, 'processing.edit.complete.btn'), - callack: _completeProcessing, - ); - final descBox = InputText( - labelTextKey: 'processing.desc', - iconData: MaterialCommunityIcons.message_text_outline, - controller: _descCtl); - final remarkBox = InputText( - labelTextKey: 'processing.remark', - iconData: Entypo.new_message, - controller: _remarkCtl); - - final img = MultiImageFile( - enabled: true, - controller: multiImgController, - title: "Receipt File", - ); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), - onPressed: () => Navigator.of(context).pop(), - ), - shadowColor: Colors.transparent, - backgroundColor: Colors.white, - title: LocalText( - context, - "processing.edit.title", - fontSize: 20, - color: primaryColor, - ), - ), - body: Padding( - padding: const EdgeInsets.all(8.0), - child: ListView( - children: [ - trackingIdBox, - fcsIDBox, - namebox, - phoneNumberBox, - marketDropdown(), - descBox, - remarkBox, - img, - completeProcessingBtn, - SizedBox( - height: 20, - ) - ], - ), - ), - ), - ); - } - - String? selectedMarket; - Widget marketDropdown() { - List _markets = Provider.of(context).markets; - List markets = _markets.map((e) => e.name).toList(); - markets.insert(0, MANAGE_MARKET); - if (!markets.contains(selectedMarket)) { - markets.insert(0, selectedMarket!); - } - - return Padding( - padding: const EdgeInsets.only(left: 5.0, right: 0), - child: Row( - children: [ - Padding( - padding: const EdgeInsets.only(left: 0, right: 10), - child: Icon(Icons.store, color: primaryColor), - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(right: 18.0), - child: LocalText( - context, - "processing.market", - color: Colors.black54, - fontSize: 16, - ), - ), - DropdownButton( - isDense: true, - value: selectedMarket, - style: TextStyle(color: Colors.black, fontSize: 14), - underline: Container( - height: 1, - color: Colors.grey, - ), - onChanged: (String? newValue) { - setState(() { - if (newValue == MANAGE_MARKET) { - selectedMarket = null; - _manageMarket(); - return; - } - selectedMarket = newValue; - }); - }, - isExpanded: true, - items: markets.map>((String? value) { - return DropdownMenuItem( - value: value, - child: Text(value ?? "", - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: value == MANAGE_MARKET - ? secondaryColor - : primaryColor)), - ); - }).toList(), - ), - ], - ), - ), - ], - ), - ); - } - - _manageMarket() { - Navigator.push( - context, - CupertinoPageRoute(builder: (context) => MarketEditor()), - ); - } - - _completeProcessing() async { - if (_user!.fcsID == null || _user!.fcsID == "") { - showMsgDialog(context, "Error", "Expected FCS-ID"); - return; - } - setState(() { - _isLoading = true; - }); - PackageModel packageModel = - Provider.of(context, listen: false); - try { - _package!.fcsID = _user!.fcsID; - _package!.desc = _descCtl.text; - _package!.remark = _remarkCtl.text; - _package!.market = selectedMarket; - await packageModel.updateProcessing(_package!, - multiImgController.getAddedFile, multiImgController.getDeletedUrl); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/processing_old/processing_info.dart b/lib/pages/processing_old/processing_info.dart deleted file mode 100644 index 0935539..0000000 --- a/lib/pages/processing_old/processing_info.dart +++ /dev/null @@ -1,194 +0,0 @@ -import 'package:fcs/domain/entities/package.dart'; -import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/pages/main/util.dart'; -import 'package:fcs/pages/package/model/package_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_text.dart'; -import 'package:fcs/pages/widgets/multi_img_controller.dart'; -import 'package:fcs/pages/widgets/multi_img_file.dart'; -import 'package:fcs/pages/widgets/progress.dart'; -import 'package:fcs/pages/widgets/status_tree.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_icons_null_safety/flutter_icons_null_safety.dart'; - -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; - -import 'processing_editor.dart'; - -final DateFormat dateFormat = DateFormat("d MMM yyyy"); - -class ProcessingInfo extends StatefulWidget { - final Package? package; - ProcessingInfo({this.package}); - - @override - _ProcessingInfoState createState() => _ProcessingInfoState(); -} - -class _ProcessingInfoState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy'); - Package? _package; - bool _isLoading = false; - MultiImgController multiImgController = MultiImgController(); - - @override - void initState() { - super.initState(); - initPackage(widget.package!); - } - - initPackage(Package package) { - setState(() { - _package = package; - multiImgController.setImageUrls = package.photoUrls; - }); - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - final trackingIdBox = DisplayText( - text: _package!.trackingID ?? "", - labelTextKey: "processing.tracking.id", - iconData: MaterialCommunityIcons.barcode_scan, - ); - var fcsIDBox = DisplayText( - text: _package!.fcsID??"", - labelTextKey: "processing.fcs.id", - icon: FcsIDIcon(), - ); - final phoneNumberBox = DisplayText( - text: _package!.phoneNumber??"", - labelTextKey: "processing.phone", - iconData: Icons.phone, - ); - final customerNameBox = DisplayText( - text: _package!.userName??"", - labelTextKey: "processing.name", - iconData: Icons.perm_identity, - ); - final marketBox = DisplayText( - text: _package!.market ?? "-", - labelTextKey: "processing.market", - iconData: Icons.store, - ); - final descBox = DisplayText( - text: _package!.desc ?? "-", - labelTextKey: "processing.desc", - iconData: MaterialCommunityIcons.message_text_outline, - ); - final remarkBox = DisplayText( - text: _package!.remark ?? "-", - labelTextKey: "processing.remark", - iconData: Entypo.new_message, - ); - final img = MultiImageFile( - enabled: false, - controller: multiImgController, - title: "Receipt File", - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), - onPressed: () => Navigator.of(context).pop(), - ), - shadowColor: Colors.transparent, - backgroundColor: Colors.white, - title: LocalText( - context, - "processing.info.title", - fontSize: 20, - color: primaryColor, - ), - actions: [ - IconButton( - icon: Icon(Icons.delete, color: primaryColor), - onPressed: _delete, - ), - IconButton( - icon: Icon(Icons.edit, color: primaryColor), - onPressed: _gotoEditor, - ), - ], - ), - body: Card( - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(10.0), - child: ListView(children: [ - trackingIdBox, - fcsIDBox, - customerNameBox, - phoneNumberBox, - marketBox, - descBox, - remarkBox, - _package!.photoUrls.length == 0 ? Container() : img, - StatusTree( - shipmentHistory: _package!.shipmentHistory, - currentStatus: _package!.status??""), - SizedBox( - height: 20, - ) - ]), - )), - ], - ), - ), - ), - ); - } - - _delete() { - showConfirmDialog(context, "processing.delete.confirm", _deletePackage); - } - - _deletePackage() async { - setState(() { - _isLoading = true; - }); - PackageModel packageModel = - Provider.of(context, listen: false); - try { - await packageModel.deleteProcessing(_package!); - Navigator.pop(context, true); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _gotoEditor() async { - bool? deleted = await Navigator.push( - context, - CupertinoPageRoute( - builder: (context) => ProcessingEditor( - package: widget.package!, - ))); - if (deleted ?? false) { - Navigator.pop(context); - } else { - PackageModel packageModel = - Provider.of(context, listen: false); - Package? p = await packageModel.getPackage(_package!.id!); - initPackage(p!); - } - } -} diff --git a/lib/pages/processing_old/processing_list.dart b/lib/pages/processing_old/processing_list.dart deleted file mode 100644 index 4e213bd..0000000 --- a/lib/pages/processing_old/processing_list.dart +++ /dev/null @@ -1,84 +0,0 @@ -import 'package:fcs/domain/entities/package.dart'; -import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/pages/package/model/package_model.dart'; -import 'package:fcs/pages/package_search/package_serach.dart'; -import 'package:fcs/pages/widgets/local_text.dart'; -import 'package:fcs/pages/widgets/progress.dart'; -import 'package:fcs/pagination/paginator_listview.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; - -import 'processing_info.dart'; -import 'processing_list_row.dart'; - -class ProcessingList extends StatefulWidget { - @override - _ProcessingListState createState() => _ProcessingListState(); -} - -class _ProcessingListState extends State { - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - var packageModel = Provider.of(context); - var packages = packageModel.activePackages; - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(CupertinoIcons.back), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: LocalText( - context, - "processing.title", - fontSize: 20, - color: Colors.white, - ), - actions: [ - IconButton( - icon: Icon( - Icons.search, - color: Colors.white, - ), - iconSize: 30, - onPressed: () => searchPackage(context, - callbackPackageSelect: _searchCallback), - ), - ], - ), - body: PaginatorListView( - paginatorListener: packages!, - rowBuilder: (p) => ProcessingListRow(package: p), - color: primaryColor, - )), - ); - } - - _searchCallback(Package package) async { - var packageModel = Provider.of(context, listen: false); - Package? _package = await packageModel.getPackage(package.id!); - if (_package == null) return; - Navigator.push( - context, - CupertinoPageRoute( - builder: (context) => ProcessingInfo(package: _package)), - ); - } -} diff --git a/lib/pages/processing_old/processing_list_row.dart b/lib/pages/processing_old/processing_list_row.dart deleted file mode 100644 index a287b2c..0000000 --- a/lib/pages/processing_old/processing_list_row.dart +++ /dev/null @@ -1,102 +0,0 @@ -import 'package:fcs/domain/entities/package.dart'; -import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/pages/main/util.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:intl/intl.dart'; - -import 'processing_info.dart'; - -typedef CallbackPackageSelect(Package package); - -class ProcessingListRow extends StatelessWidget { - final Package? package; - final CallbackPackageSelect? callbackPackageSelect; - final double dotSize = 15.0; - final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); - - ProcessingListRow({Key? key, this.package, this.callbackPackageSelect}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return InkWell( - onTap: () { - if (callbackPackageSelect != null) { - callbackPackageSelect!(package!); - return; - } - Navigator.push( - context, - CupertinoPageRoute( - builder: (context) => ProcessingInfo(package: package)), - ); - }, - child: Container( - padding: EdgeInsets.only(left: 15, right: 15), - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), - child: new Row( - children: [ - Container( - padding: EdgeInsets.only(left: 5, right: 10), - child: Icon( - FontAwesomeIcons.dropbox, - color: primaryColor, - size: 30, - ), - ), - new Expanded( - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - package!.id == null ? '' : package!.trackingID!, - style: new TextStyle( - fontSize: 15.0, color: Colors.black), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - package!.market == null ? '' : package!.market!, - style: new TextStyle( - fontSize: 15.0, color: Colors.black), - ), - ), - ], - ), - ), - ], - ), - ), - ), - Column( - children: [ - Padding( - padding: const EdgeInsets.all(3.0), - child: getStatus(package!.status ?? ""), - ), - Padding( - padding: const EdgeInsets.all(0), - child: new Text( - package!.currentStatusDate != null - ? dateFormat.format(package!.currentStatusDate!) - : '', - style: new TextStyle(fontSize: 15.0, color: Colors.grey), - ), - ), - ], - ) - ], - ), - ), - ); - } -} diff --git a/lib/pages/receiving/receiving_list.dart b/lib/pages/receiving/receiving_list.dart index 225aef3..765a675 100644 --- a/lib/pages/receiving/receiving_list.dart +++ b/lib/pages/receiving/receiving_list.dart @@ -21,20 +21,10 @@ class ReceivingList extends StatefulWidget { class _ReceivingListState extends State { bool _isLoading = false; - @override - void initState() { - super.initState(); - } - - @override - void dispose() { - super.dispose(); - } - @override Widget build(BuildContext context) { var packageModel = Provider.of(context); - var packages = packageModel.activePackages; + var activePackages = packageModel.activePackages; return LocalProgress( inAsyncCall: _isLoading, @@ -73,7 +63,7 @@ class _ReceivingListState extends State { backgroundColor: primaryColor, ), body: PaginatorListView( - paginatorListener: packages!, + paginatorListener: activePackages!, rowBuilder: (p) => ReceivingListRow(package: p), color: primaryColor)), ); diff --git a/lib/pages/shipment/box_row.dart b/lib/pages/shipment/box_row.dart index 7e9d589..d4793a2 100644 --- a/lib/pages/shipment/box_row.dart +++ b/lib/pages/shipment/box_row.dart @@ -1,5 +1,4 @@ import 'package:fcs/domain/entities/carton.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class BoxRow extends StatelessWidget { diff --git a/lib/pages/shipment/shipment_list.dart b/lib/pages/shipment/shipment_list.dart deleted file mode 100644 index b1b640a..0000000 --- a/lib/pages/shipment/shipment_list.dart +++ /dev/null @@ -1,149 +0,0 @@ -import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/pages/shipment/model/shipment_model.dart'; -import 'package:fcs/pages/widgets/local_popup_menu_button.dart'; -import 'package:fcs/pages/widgets/local_popupmenu.dart'; -import 'package:fcs/pages/widgets/local_text.dart'; -import 'package:fcs/pages/widgets/progress.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:provider/provider.dart'; - -import 'package:flutter/material.dart'; - -import 'shipment_editor.dart'; -import 'shipment_list_row.dart'; - -class ShipmentList extends StatefulWidget { - final bool forCustomer; - - const ShipmentList({Key? key, this.forCustomer = true}) : super(key: key); - @override - _ShipmentListState createState() => _ShipmentListState(); -} - -class _ShipmentListState extends State { - bool _isLoading = false; - var _controller = ScrollController(); - bool _forCustomer = true; - - @override - void initState() { - super.initState(); - _forCustomer = widget.forCustomer; - _controller.addListener(() async { - if (_controller.position.pixels == _controller.position.maxScrollExtent) { - Provider.of(context, listen: false) - .loadMore(isCustomer: widget.forCustomer); - } - }); - - Provider.of(context, listen: false) - .initData(widget.forCustomer); - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - ShipmentModel shipmentModel = Provider.of(context); - final popupMenu = LocalPopupMenuButton( - popmenus: _forCustomer - ? [ - LocalPopupMenu( - id: 1, textKey: "shipment.popupmenu.active", selected: true), - LocalPopupMenu(id: 2, textKey: "shipment.popupmenu.delivered"), - ] - : [ - LocalPopupMenu( - id: 1, textKey: "shipment.popupmenu.active", selected: true), - LocalPopupMenu(id: 2, textKey: "shipment.popupmenu.delivered"), - LocalPopupMenu(id: 3, textKey: "shipment.popupmenu.mypickup"), - ], - popupMenuCallback: (p) => this.setState(() { - shipmentModel.menuSelectedIndex = p.id; - if (p.id == 3) { - Provider.of(context, listen: false) - .initData(widget.forCustomer, myPickup: true); - } else { - Provider.of(context, listen: false) - .initData(widget.forCustomer, myPickup: false); - } - }), - ); - return LocalProgress( - inAsyncCall: _isLoading, - child: DefaultTabController( - length: 3, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(CupertinoIcons.back), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: LocalText(context, "shipment", - fontSize: 18, color: Colors.white), - actions: [popupMenu], - ), - floatingActionButton: widget.forCustomer - ? FloatingActionButton.extended( - onPressed: () { - _newPickup(); - }, - icon: Icon(Icons.add), - label: - LocalText(context, "shipment.new", color: Colors.white), - backgroundColor: primaryColor, - ) - : Container(), - body: Column( - children: [ - Expanded( - child: RefreshIndicator( - child: ListView.separated( - controller: _controller, - separatorBuilder: (context, index) => Divider( - color: Colors.grey, - height: 1, - ), - scrollDirection: Axis.vertical, - itemCount: shipmentModel.shipments.length, - itemBuilder: (BuildContext context, int index) { - return ShipmentListRow( - key: ValueKey(shipmentModel.shipments[index].id), - shipment: shipmentModel.shipments[index], - isCustomer: widget.forCustomer, - ); - }), - onRefresh: () => - shipmentModel.refresh(isCustomer: widget.forCustomer), - ), - ), - shipmentModel.isLoading - ? Container( - padding: EdgeInsets.all(8), - color: primaryColor, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Loading...", - style: TextStyle(color: Colors.white)), - ], - ), - ) - : Container(), - ], - ), - ), - ), - ); - } - - _newPickup() { - Navigator.of(context) - .push(CupertinoPageRoute(builder: (context) => ShipmentEditor())); - } -} diff --git a/lib/pages/shipment/shipment_list_row.dart b/lib/pages/shipment/shipment_list_row.dart deleted file mode 100644 index 329e29b..0000000 --- a/lib/pages/shipment/shipment_list_row.dart +++ /dev/null @@ -1,98 +0,0 @@ -import 'package:fcs/domain/entities/shipment.dart'; -import 'package:fcs/helpers/theme.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_icons_null_safety/flutter_icons_null_safety.dart'; - -import '../main/util.dart'; -import 'shipment_info.dart'; - -class ShipmentListRow extends StatelessWidget { - final Shipment? shipment; - final bool? isCustomer; - const ShipmentListRow({Key? key, this.shipment, this.isCustomer}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return InkWell( - onTap: () { - Navigator.of(context).push(CupertinoPageRoute( - builder: (context) => ShipmentInfo( - shipment: shipment, - isCustomer: isCustomer, - ))); - }, - child: Container( - padding: EdgeInsets.only(left: 15, right: 15), - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), - child: new Row( - children: [ - Padding( - padding: EdgeInsets.all(5.0), - child: Icon( - SimpleLineIcons.direction, - color: primaryColor, - )), - new Expanded( - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - shipment!.shipmentNumber ?? "", - style: new TextStyle( - fontSize: 15.0, color: Colors.black), - ), - ), - // Padding( - // padding: const EdgeInsets.only(left: 10.0, top: 3), - // child: new Text( - // "Last ${shipment.last ?? 0} days", - // style: new TextStyle( - // fontSize: 15.0, color: Colors.grey), - // ), - // ) - ], - ), - ), - ], - ), - ), - ), - Column( - children: [ - Padding( - padding: const EdgeInsets.all(0), - child: getStatus(shipment!.status ?? ""), - ), - // Padding( - // padding: const EdgeInsets.only(left: 8.0, top: 5, bottom: 5), - // child: Row( - // children: [ - // new Text( - // "(${pickUp.totalWeight ?? "0"}) lb ", - // style: - // new TextStyle(fontSize: 15.0, color: Colors.grey), - // ), - // new Text( - // "(${pickUp.totalCount ?? "0"}) cartons ", - // style: - // new TextStyle(fontSize: 15.0, color: Colors.grey), - // ), - // ], - // ), - // ), - ], - ) - ], - ), - ), - ); - } -} diff --git a/lib/pages/staff/model/staff_model.dart b/lib/pages/staff/model/staff_model.dart index e4a0b7a..fabf82b 100644 --- a/lib/pages/staff/model/staff_model.dart +++ b/lib/pages/staff/model/staff_model.dart @@ -9,53 +9,47 @@ import 'package:fcs/helpers/firebase_helper.dart'; import 'package:fcs/pages/main/model/base_model.dart'; import 'package:logging/logging.dart'; +import '../../../pagination/paginator_listener.dart'; + class StaffModel extends BaseModel { final log = Logger('StaffModel'); - StreamSubscription? listener; - StreamSubscription? privilegeListener; + PaginatorListener? getStaffs; - List employees = []; + StreamSubscription? privilegeListener; List privileges = []; @override void privilegeChanged() { super.privilegeChanged(); _loadPrivileges(); - _loadEmployees(); } @override logout() async { - if (listener != null) listener!.cancel(); + getStaffs?.close(); if (privilegeListener != null) privilegeListener!.cancel(); - employees = []; privileges = []; } - Future _loadEmployees() async { + loadPaginationStaffs() { if (user == null || !user!.hasStaffs()) return; - try { - if (listener != null) listener!.cancel(); + String path = "/$user_collection"; + Query col = FirebaseFirestore.instance + .collection(path) + .where("is_employee", isEqualTo: true) + .where("is_sys_admin", isEqualTo: false); - listener = FirebaseFirestore.instance - .collection("/$user_collection") - .where("is_employee", isEqualTo: true) - .where("is_sys_admin", isEqualTo: false) - .snapshots() - .listen((QuerySnapshot snapshot) { - employees.clear(); - employees = snapshot.docs.map((documentSnapshot) { - var user = User.fromMap( - documentSnapshot.data() as Map, - documentSnapshot.id); - return user; - }).toList(); - notifyListeners(); - }); - } catch (e) { - log.warning("Error!! $e"); - } + Query pageQuery = FirebaseFirestore.instance + .collection(path) + .where("is_employee", isEqualTo: true) + .where("is_sys_admin", isEqualTo: false) + .orderBy("update_time", descending: true); + + getStaffs?.close(); + getStaffs = PaginatorListener( + col, pageQuery, (data, id) => User.fromMap(data, id), + rowPerLoad: 30); } Future _loadPrivileges() async { diff --git a/lib/pages/staff/staff_list.dart b/lib/pages/staff/staff_list.dart index a56232a..560097c 100644 --- a/lib/pages/staff/staff_list.dart +++ b/lib/pages/staff/staff_list.dart @@ -9,6 +9,7 @@ import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; +import '../../pagination/paginator_listview.dart'; import 'staff_editor.dart'; class StaffList extends StatefulWidget { @@ -21,6 +22,12 @@ class _StaffListState extends State { final double dotSize = 15.0; bool _isLoading = false; + @override + void initState() { + context.read().loadPaginationStaffs(); + super.initState(); + } + @override Widget build(BuildContext context) { StaffModel staffModel = Provider.of(context); @@ -28,42 +35,33 @@ class _StaffListState extends State { return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(CupertinoIcons.back), - onPressed: () => Navigator.of(context).pop(), + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: LocalText( + context, + 'staff.list.title', + color: Colors.white, + fontSize: 20, + ), ), - backgroundColor: primaryColor, - title: LocalText( - context, - 'staff.list.title', - color: Colors.white, - fontSize: 20, + floatingActionButton: FloatingActionButton.extended( + onPressed: () { + Navigator.of(context).push( + CupertinoPageRoute(builder: (context) => StaffEditor())); + }, + icon: Icon(Icons.add), + label: LocalText(context, "staff.new", color: Colors.white), + backgroundColor: primaryColor, ), - ), - floatingActionButton: FloatingActionButton.extended( - onPressed: () { - Navigator.of(context) - .push(CupertinoPageRoute(builder: (context) => StaffEditor())); - }, - icon: Icon(Icons.add), - label: LocalText(context, "staff.new", color: Colors.white), - backgroundColor: primaryColor, - ), - body: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - height: 1, - ), - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: staffModel.employees.length, - itemBuilder: (BuildContext context, int index) { - User user = staffModel.employees[index]; - return _item(user); - }), - ), + body: PaginatorListView( + paginatorListener: staffModel.getStaffs!, + rowBuilder: (p) => _item(p), + color: primaryColor)), ); } diff --git a/lib/pages/widgets/local_app_bar.dart b/lib/pages/widgets/local_app_bar.dart new file mode 100644 index 0000000..a709794 --- /dev/null +++ b/lib/pages/widgets/local_app_bar.dart @@ -0,0 +1,53 @@ +import 'package:fcs/helpers/theme.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import 'local_text.dart'; + +class LocalAppBar extends StatelessWidget implements PreferredSizeWidget { + final String? labelKey; + final Color? backgroundColor; + final Color? labelColor; + final Color? arrowColor; + final List? actions; + final Widget? titleWidget; + final Function()? onBack; + + const LocalAppBar( + {Key? key, + this.labelKey, + this.backgroundColor = primaryColor, + this.labelColor, + this.arrowColor = Colors.white, + this.actions, + this.titleWidget, + this.onBack}) + : super(key: key); + + @override + Size get preferredSize => const Size.fromHeight(56); + + @override + Widget build(BuildContext context) { + return AppBar( + elevation: 0, + centerTitle: true, + leading: IconButton( + icon: Icon(CupertinoIcons.back, color: arrowColor, size: 25), + onPressed: onBack), + shadowColor: Colors.transparent, + backgroundColor: backgroundColor, + surfaceTintColor: backgroundColor, + title: titleWidget ?? + (labelKey != null + ? LocalText( + context, + labelKey!, + color: Colors.white, + fontSize: 20, + ) + : const SizedBox()), + actions: actions, + ); + } +} diff --git a/lib/pages/widgets/number_cell.dart b/lib/pages/widgets/number_cell.dart deleted file mode 100644 index 8012f2d..0000000 --- a/lib/pages/widgets/number_cell.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:intl/intl.dart'; -import 'package:fcs/helpers/theme.dart' as theme; - -class NumberCell extends StatelessWidget { - final int number; - final numberFormatter; - final TextStyle? textStyle; - - NumberCell(this.number, {Key? key, this.textStyle}) - : numberFormatter = new NumberFormat("#,###"), - super(key: key); - - @override - Widget build(BuildContext context) { - return new Text(numberFormatter.format(this.number), - style: textStyle == null ? theme.textStyle : textStyle); - } -} diff --git a/lib/pages/widgets/title_with_add_button.dart b/lib/pages/widgets/title_with_add_button.dart deleted file mode 100644 index e22fb69..0000000 --- a/lib/pages/widgets/title_with_add_button.dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/pages/widgets/local_text.dart'; -import 'package:flutter/material.dart'; - -import 'callbacks.dart'; - -class TitleWithAddButton extends StatelessWidget { - final IconData? iconData; - final String? titleKey; - final OnTap? onTap; - - const TitleWithAddButton({Key? key, this.iconData, this.titleKey, this.onTap}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Row( - children: [ - Padding( - padding: const EdgeInsets.only(right: 15.0), - child: Icon( - this.iconData, - color: primaryColor, - ), - ), - LocalText( - context, - titleKey!, - color: Colors.black54, - fontSize: 20, - ) - ], - ), - Spacer(), - onTap == null - ? Container() - : Padding( - padding: const EdgeInsets.only(right: 0), - child: IconButton( - onPressed: () => onTap!(), - icon: Icon( - Icons.add_circle, - color: primaryColor, - )), - ) - ], - ); - } -}