diff --git a/assets/release_notes.md b/assets/release_notes.md index 4b85e852..3aab9fb9 100644 --- a/assets/release_notes.md +++ b/assets/release_notes.md @@ -1,3 +1,8 @@ +### TBD - ??? +--- + +- Improved UX across the entire app + ### 0.19.1 - July 2025 --- - Fixes bug related to barcode scanning with certain devices diff --git a/lib/inventree/company.dart b/lib/inventree/company.dart index 43f7d51b..f9f6b426 100644 --- a/lib/inventree/company.dart +++ b/lib/inventree/company.dart @@ -5,6 +5,7 @@ import "package:inventree/api.dart"; import "package:inventree/inventree/model.dart"; import "package:inventree/inventree/purchase_order.dart"; import "package:inventree/widget/company/company_detail.dart"; +import "package:inventree/widget/company/supplier_part_detail.dart"; /* * The InvenTreeCompany class represents the Company model in the InvenTree database. @@ -152,6 +153,14 @@ class InvenTreeSupplierPart extends InvenTreeModel { @override List get rolesRequired => ["part", "purchase_order"]; + @override + Future goToDetailPage(BuildContext context) async { + return Navigator.push( + context, + MaterialPageRoute(builder: (context) => SupplierPartDetailWidget(this)), + ); + } + @override Map> formFields() { Map> fields = { diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ff6fa80f..7e02053b 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -391,6 +391,9 @@ "editLineItem": "Edit Line Item", "@editLineItem": {}, + "email": "Email", + "@email": {}, + "enterPassword": "Enter password", "@enterPassword": {}, @@ -924,6 +927,9 @@ "permissionRequired": "Permission Required", "@permissionRequired": {}, + "phone": "Phone", + "@phone": {}, + "printLabel": "Print Label", "@printLabel": {}, diff --git a/lib/widget/company/company_detail.dart b/lib/widget/company/company_detail.dart index 076a1e66..64356d71 100644 --- a/lib/widget/company/company_detail.dart +++ b/lib/widget/company/company_detail.dart @@ -10,6 +10,7 @@ import "package:inventree/inventree/company.dart"; import "package:inventree/inventree/purchase_order.dart"; import "package:inventree/inventree/sales_order.dart"; import "package:inventree/widget/attachment_widget.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/order/purchase_order_list.dart"; import "package:inventree/widget/order/sales_order_list.dart"; import "package:inventree/widget/refreshable_state.dart"; @@ -240,8 +241,10 @@ class _CompanyDetailState extends RefreshableState { if (widget.company.website.isNotEmpty) { tiles.add( ListTile( - title: Text("${widget.company.website}"), + title: Text(L10().website), + subtitle: Text("${widget.company.website}"), leading: Icon(TablerIcons.globe, color: COLOR_ACTION), + trailing: LinkIcon(external: true), onTap: () async { openLink(widget.company.website); }, @@ -254,8 +257,10 @@ class _CompanyDetailState extends RefreshableState { if (widget.company.email.isNotEmpty) { tiles.add( ListTile( - title: Text("${widget.company.email}"), + title: Text(L10().email), + subtitle: Text("${widget.company.email}"), leading: Icon(TablerIcons.at, color: COLOR_ACTION), + trailing: LinkIcon(external: true), onTap: () async { openLink("mailto:${widget.company.email}"); }, @@ -268,8 +273,10 @@ class _CompanyDetailState extends RefreshableState { if (widget.company.phone.isNotEmpty) { tiles.add( ListTile( - title: Text("${widget.company.phone}"), + title: Text(L10().phone), + subtitle: Text("${widget.company.phone}"), leading: Icon(TablerIcons.phone, color: COLOR_ACTION), + trailing: LinkIcon(external: true), onTap: () { openLink("tel:${widget.company.phone}"); }, @@ -283,8 +290,10 @@ class _CompanyDetailState extends RefreshableState { if (widget.company.link.isNotEmpty) { tiles.add( ListTile( - title: Text("${widget.company.link}"), + title: Text(L10().link), + subtitle: Text("${widget.company.link}"), leading: Icon(TablerIcons.link, color: COLOR_ACTION), + trailing: LinkIcon(external: true), onTap: () { widget.company.openLink(); }, @@ -304,7 +313,7 @@ class _CompanyDetailState extends RefreshableState { ListTile( title: Text(L10().supplierParts), leading: Icon(TablerIcons.building, color: COLOR_ACTION), - trailing: Text(supplierPartCount.toString()), + trailing: LinkIcon(text: supplierPartCount.toString()), onTap: () { Navigator.push( context, @@ -323,7 +332,7 @@ class _CompanyDetailState extends RefreshableState { ListTile( title: Text(L10().purchaseOrders), leading: Icon(TablerIcons.shopping_cart, color: COLOR_ACTION), - trailing: Text("${outstandingPurchaseOrders}"), + trailing: LinkIcon(text: "${outstandingPurchaseOrders}"), onTap: () { Navigator.push( context, @@ -343,7 +352,7 @@ class _CompanyDetailState extends RefreshableState { ListTile( title: Text(L10().suppliedParts), leading: Icon(TablerIcons.box), - trailing: Text("${company.partSuppliedCount}"), + trailing: LargeText("${company.partSuppliedCount}"), ) ); */ @@ -358,7 +367,7 @@ class _CompanyDetailState extends RefreshableState { ListTile( title: Text(L10().salesOrders), leading: Icon(TablerIcons.truck, color: COLOR_ACTION), - trailing: Text("${outstandingSalesOrders}"), + trailing: LinkIcon(text: "${outstandingSalesOrders}"), onTap: () { Navigator.push( context, @@ -377,6 +386,7 @@ class _CompanyDetailState extends RefreshableState { tiles.add( ListTile( title: Text(L10().notes), + subtitle: Text(widget.company.notes), leading: Icon(TablerIcons.note), onTap: null, ), @@ -387,7 +397,9 @@ class _CompanyDetailState extends RefreshableState { ListTile( title: Text(L10().attachments), leading: Icon(TablerIcons.file, color: COLOR_ACTION), - trailing: attachmentCount > 0 ? Text(attachmentCount.toString()) : null, + trailing: LinkIcon( + text: attachmentCount > 0 ? attachmentCount.toString() : null, + ), onTap: () { Navigator.push( context, diff --git a/lib/widget/company/supplier_part_detail.dart b/lib/widget/company/supplier_part_detail.dart index df00b2f7..92cf2de6 100644 --- a/lib/widget/company/supplier_part_detail.dart +++ b/lib/widget/company/supplier_part_detail.dart @@ -1,9 +1,9 @@ import "package:flutter/material.dart"; import "package:flutter_speed_dial/flutter_speed_dial.dart"; import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:url_launcher/url_launcher.dart"; -import "package:inventree/api.dart"; import "package:inventree/app_colors.dart"; import "package:inventree/l10.dart"; @@ -117,7 +117,7 @@ class _SupplierPartDisplayState title: Text(L10().internalPart), subtitle: Text(widget.supplierPart.partName), leading: Icon(TablerIcons.box, color: COLOR_ACTION), - trailing: InvenTreeAPI().getThumbnail(widget.supplierPart.partImage), + trailing: LinkIcon(), onTap: () async { showLoadingOverlay(); final part = await InvenTreePart().get(widget.supplierPart.partId); @@ -149,9 +149,7 @@ class _SupplierPartDisplayState title: Text(L10().supplier), subtitle: Text(widget.supplierPart.supplierName), leading: Icon(TablerIcons.building, color: COLOR_ACTION), - trailing: InvenTreeAPI().getThumbnail( - widget.supplierPart.supplierImage, - ), + trailing: LinkIcon(), onTap: () async { showLoadingOverlay(); var supplier = await InvenTreeCompany().get( @@ -182,9 +180,7 @@ class _SupplierPartDisplayState title: Text(L10().manufacturer), subtitle: Text(widget.supplierPart.manufacturerName), leading: Icon(TablerIcons.building_factory_2, color: COLOR_ACTION), - trailing: InvenTreeAPI().getThumbnail( - widget.supplierPart.manufacturerImage, - ), + trailing: LinkIcon(), onTap: () async { showLoadingOverlay(); var supplier = await InvenTreeCompany().get( @@ -204,6 +200,7 @@ class _SupplierPartDisplayState title: Text(L10().manufacturerPartNumber), subtitle: Text(widget.supplierPart.MPN), leading: Icon(TablerIcons.hash, color: COLOR_ACTION), + trailing: LinkIcon(), onTap: () async { showLoadingOverlay(); var manufacturerPart = await InvenTreeManufacturerPart().get( @@ -236,7 +233,7 @@ class _SupplierPartDisplayState : null, leading: Icon(TablerIcons.package), trailing: widget.supplierPart.pack_quantity.isNotEmpty - ? Text(widget.supplierPart.pack_quantity) + ? LargeText(widget.supplierPart.pack_quantity) : null, ), ); @@ -245,8 +242,10 @@ class _SupplierPartDisplayState if (widget.supplierPart.link.isNotEmpty) { tiles.add( ListTile( - title: Text(widget.supplierPart.link), + title: Text(L10().link), + subtitle: Text(widget.supplierPart.link), leading: Icon(TablerIcons.link, color: COLOR_ACTION), + trailing: LinkIcon(external: true), onTap: () async { var uri = Uri.tryParse(widget.supplierPart.link); if (uri != null && await canLaunchUrl(uri)) { @@ -260,7 +259,8 @@ class _SupplierPartDisplayState if (widget.supplierPart.note.isNotEmpty) { tiles.add( ListTile( - title: Text(widget.supplierPart.note), + title: Text(L10().notes), + subtitle: Text(widget.supplierPart.note), leading: Icon(TablerIcons.pencil), ), ); diff --git a/lib/widget/company/supplier_part_list.dart b/lib/widget/company/supplier_part_list.dart index 65769741..c820a67d 100644 --- a/lib/widget/company/supplier_part_list.dart +++ b/lib/widget/company/supplier_part_list.dart @@ -8,7 +8,6 @@ import "package:inventree/inventree/model.dart"; import "package:inventree/widget/paginator.dart"; import "package:inventree/widget/refreshable_state.dart"; -import "package:inventree/widget/company/supplier_part_detail.dart"; /* * Widget for displaying a list of Supplier Part instances @@ -93,12 +92,7 @@ class _PaginatedSupplierPartListState leading: InvenTreeAPI().getThumbnail(supplierPart.supplierImage), trailing: InvenTreeAPI().getThumbnail(supplierPart.partImage), onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SupplierPartDetailWidget(supplierPart), - ), - ); + supplierPart.goToDetailPage(context); }, ); } diff --git a/lib/widget/link_icon.dart b/lib/widget/link_icon.dart new file mode 100644 index 00000000..4a835eb3 --- /dev/null +++ b/lib/widget/link_icon.dart @@ -0,0 +1,44 @@ +/* + * An icon component to indicate that pressing on an item will change the page. + */ + +import "package:cached_network_image/cached_network_image.dart"; +import "package:flutter/cupertino.dart"; +import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; +import "package:inventree/app_colors.dart"; + +Widget LargeText( + String text, { + double size = 14.0, + bool bold = false, + Color? color, +}) { + // Return a large text widget with specified text + return Text( + text, + style: TextStyle( + fontSize: size, + fontWeight: bold ? FontWeight.bold : FontWeight.normal, + color: color, + ), + ); +} + +Widget LinkIcon({ + bool external = false, + String? text, + CachedNetworkImage? image, +}) { + // Return a row of items with an icon and text + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (text != null) ...[LargeText(text)], + if (image != null) ...[image], + Icon( + external ? TablerIcons.external_link : TablerIcons.chevron_right, + color: COLOR_ACTION, + ), + ], + ); +} diff --git a/lib/widget/order/extra_line_detail.dart b/lib/widget/order/extra_line_detail.dart index 055a58ec..490f8332 100644 --- a/lib/widget/order/extra_line_detail.dart +++ b/lib/widget/order/extra_line_detail.dart @@ -3,6 +3,7 @@ import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; import "package:inventree/helpers.dart"; import "package:inventree/l10.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/snacks.dart"; @@ -70,36 +71,44 @@ class _ExtraLineDetailWidgetState tiles.add( ListTile( title: Text(L10().reference), - trailing: Text(widget.item.reference), + subtitle: Text(widget.item.reference), + leading: Icon(TablerIcons.hash), ), ); tiles.add( ListTile( title: Text(L10().description), - trailing: Text(widget.item.description), + subtitle: Text(widget.item.description), + leading: Icon(TablerIcons.info_circle), ), ); tiles.add( ListTile( title: Text(L10().quantity), - trailing: Text(widget.item.quantity.toString()), + trailing: LargeText(widget.item.quantity.toString()), + leading: Icon(TablerIcons.progress), ), ); tiles.add( ListTile( title: Text(L10().unitPrice), - trailing: Text( + trailing: LargeText( renderCurrency(widget.item.price, widget.item.priceCurrency), ), + leading: Icon(TablerIcons.currency_dollar), ), ); if (widget.item.notes.isNotEmpty) { tiles.add( - ListTile(title: Text(L10().notes), subtitle: Text(widget.item.notes)), + ListTile( + title: Text(L10().notes), + subtitle: Text(widget.item.notes), + leading: Icon(TablerIcons.note), + ), ); } diff --git a/lib/widget/order/po_extra_line_list.dart b/lib/widget/order/po_extra_line_list.dart index 3ede5082..b9d953fd 100644 --- a/lib/widget/order/po_extra_line_list.dart +++ b/lib/widget/order/po_extra_line_list.dart @@ -5,6 +5,7 @@ import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; import "package:inventree/l10.dart"; import "package:inventree/inventree/model.dart"; import "package:inventree/inventree/purchase_order.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/paginator.dart"; import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/snacks.dart"; @@ -110,7 +111,7 @@ class _PaginatedPOExtraLineListState return ListTile( title: Text(line.reference), subtitle: Text(line.description), - trailing: Text(line.quantity.toString()), + trailing: LargeText(line.quantity.toString(), size: 14), onTap: () { line.goToDetailPage(context).then((_) { refresh(); diff --git a/lib/widget/order/po_line_detail.dart b/lib/widget/order/po_line_detail.dart index cb0c8555..7faf4975 100644 --- a/lib/widget/order/po_line_detail.dart +++ b/lib/widget/order/po_line_detail.dart @@ -11,11 +11,11 @@ import "package:inventree/inventree/company.dart"; import "package:inventree/inventree/part.dart"; import "package:inventree/inventree/purchase_order.dart"; import "package:inventree/inventree/stock.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/progress.dart"; import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/snacks.dart"; -import "package:inventree/widget/company/supplier_part_detail.dart"; /* * Widget for displaying detail view of a single PurchaseOrderLineItem @@ -145,7 +145,7 @@ class _POLineDetailWidgetState extends RefreshableState { title: Text(L10().internalPart), subtitle: Text(widget.item.partName), leading: Icon(TablerIcons.box, color: COLOR_ACTION), - trailing: api.getThumbnail(widget.item.partImage), + trailing: LinkIcon(image: api.getThumbnail(widget.item.partImage)), onTap: () async { showLoadingOverlay(); var part = await InvenTreePart().get(widget.item.partId); @@ -164,6 +164,7 @@ class _POLineDetailWidgetState extends RefreshableState { title: Text(L10().supplierPart), subtitle: Text(widget.item.SKU), leading: Icon(TablerIcons.building, color: COLOR_ACTION), + trailing: LinkIcon(), onTap: () async { showLoadingOverlay(); var part = await InvenTreeSupplierPart().get( @@ -172,12 +173,7 @@ class _POLineDetailWidgetState extends RefreshableState { hideLoadingOverlay(); if (part is InvenTreeSupplierPart) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SupplierPartDetailWidget(part), - ), - ); + part.goToDetailPage(context); } }, ), @@ -200,11 +196,9 @@ class _POLineDetailWidgetState extends RefreshableState { ListTile( title: Text(L10().received), subtitle: ProgressBar(widget.item.progressRatio), - trailing: Text( + trailing: LargeText( widget.item.progressString, - style: TextStyle( - color: widget.item.isComplete ? COLOR_SUCCESS : COLOR_WARNING, - ), + color: widget.item.isComplete ? COLOR_SUCCESS : COLOR_WARNING, ), leading: Icon(TablerIcons.progress), ), @@ -226,7 +220,7 @@ class _POLineDetailWidgetState extends RefreshableState { ListTile( title: Text(L10().unitPrice), leading: Icon(TablerIcons.currency_dollar), - trailing: Text( + trailing: LargeText( renderCurrency( widget.item.purchasePrice, widget.item.purchasePriceCurrency, diff --git a/lib/widget/order/po_line_list.dart b/lib/widget/order/po_line_list.dart index 45a27024..2de44c4a 100644 --- a/lib/widget/order/po_line_list.dart +++ b/lib/widget/order/po_line_list.dart @@ -7,6 +7,7 @@ import "package:inventree/l10.dart"; import "package:inventree/inventree/company.dart"; import "package:inventree/inventree/model.dart"; import "package:inventree/inventree/purchase_order.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/paginator.dart"; import "package:inventree/widget/order/po_line_detail.dart"; @@ -80,11 +81,9 @@ class _PaginatedPOLineListState return ListTile( title: Text(supplierPart.SKU), subtitle: Text(item.partName), - trailing: Text( + trailing: LargeText( item.progressString, - style: TextStyle( - color: item.isComplete ? COLOR_SUCCESS : COLOR_WARNING, - ), + color: item.isComplete ? COLOR_SUCCESS : COLOR_WARNING, ), leading: InvenTreeAPI().getThumbnail(supplierPart.partImage), onTap: () async { diff --git a/lib/widget/order/purchase_order_detail.dart b/lib/widget/order/purchase_order_detail.dart index f515cf86..47993179 100644 --- a/lib/widget/order/purchase_order_detail.dart +++ b/lib/widget/order/purchase_order_detail.dart @@ -14,8 +14,8 @@ import "package:inventree/inventree/stock.dart"; import "package:inventree/inventree/purchase_order.dart"; import "package:inventree/widget/dialogs.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/order/po_extra_line_list.dart"; -import "package:inventree/widget/stock/location_display.dart"; import "package:inventree/widget/order/po_line_list.dart"; import "package:inventree/widget/attachment_widget.dart"; @@ -347,11 +347,9 @@ class _PurchaseOrderDetailState title: Text(widget.order.reference), subtitle: Text(widget.order.description), leading: supplier == null ? null : api.getThumbnail(supplier.thumbnail), - trailing: Text( + trailing: LargeText( api.PurchaseOrderStatus.label(widget.order.status), - style: TextStyle( - color: api.PurchaseOrderStatus.color(widget.order.status), - ), + color: api.PurchaseOrderStatus.color(widget.order.status), ), ), ); @@ -382,6 +380,7 @@ class _PurchaseOrderDetailState title: Text(L10().supplier), subtitle: Text(supplier.name), leading: Icon(TablerIcons.building, color: COLOR_ACTION), + trailing: LinkIcon(), onTap: () { supplier.goToDetailPage(context); }, @@ -406,14 +405,8 @@ class _PurchaseOrderDetailState title: Text(L10().destination), subtitle: Text(destination!.name), leading: Icon(TablerIcons.map_pin, color: COLOR_ACTION), - onTap: () => { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => LocationDisplayWidget(destination), - ), - ), - }, + trailing: LinkIcon(), + onTap: () => {destination!.goToDetailPage(context)}, ), ); } @@ -430,9 +423,9 @@ class _PurchaseOrderDetailState maximum: widget.order.lineItemCount.toDouble(), ), leading: Icon(TablerIcons.clipboard_check), - trailing: Text( + trailing: LargeText( "${completedLines} / ${widget.order.lineItemCount}", - style: TextStyle(color: lineColor), + color: lineColor, ), ), ); @@ -442,7 +435,7 @@ class _PurchaseOrderDetailState ListTile( title: Text(L10().extraLineItems), leading: Icon(TablerIcons.clipboard_list, color: COLOR_ACTION), - trailing: Text(extraLineCount.toString()), + trailing: LinkIcon(text: extraLineCount.toString()), onTap: () => { Navigator.push( context, @@ -461,7 +454,7 @@ class _PurchaseOrderDetailState ListTile( title: Text(L10().totalPrice), leading: Icon(TablerIcons.currency_dollar), - trailing: Text( + trailing: LargeText( renderCurrency( widget.order.totalPrice, widget.order.totalPriceCurrency, @@ -474,7 +467,7 @@ class _PurchaseOrderDetailState tiles.add( ListTile( title: Text(L10().issueDate), - trailing: Text(widget.order.issueDate), + trailing: LargeText(widget.order.issueDate), leading: Icon(TablerIcons.calendar), ), ); @@ -484,7 +477,7 @@ class _PurchaseOrderDetailState tiles.add( ListTile( title: Text(L10().startDate), - trailing: Text(widget.order.startDate), + trailing: LargeText(widget.order.startDate), leading: Icon(TablerIcons.calendar), ), ); @@ -494,7 +487,7 @@ class _PurchaseOrderDetailState tiles.add( ListTile( title: Text(L10().targetDate), - trailing: Text(widget.order.targetDate), + trailing: LargeText(widget.order.targetDate), leading: Icon(TablerIcons.calendar), ), ); @@ -504,7 +497,7 @@ class _PurchaseOrderDetailState tiles.add( ListTile( title: Text(L10().completionDate), - trailing: Text(widget.order.completionDate), + trailing: LargeText(widget.order.completionDate), leading: Icon(TablerIcons.calendar), ), ); @@ -521,7 +514,7 @@ class _PurchaseOrderDetailState ? TablerIcons.users : TablerIcons.user, ), - trailing: Text(widget.order.responsibleName), + trailing: LargeText(widget.order.responsibleName), ), ); } @@ -531,6 +524,7 @@ class _PurchaseOrderDetailState ListTile( title: Text(L10().notes), leading: Icon(TablerIcons.note, color: COLOR_ACTION), + trailing: LinkIcon(), onTap: () { Navigator.push( context, @@ -545,7 +539,9 @@ class _PurchaseOrderDetailState ListTile( title: Text(L10().attachments), leading: Icon(TablerIcons.file, color: COLOR_ACTION), - trailing: attachmentCount > 0 ? Text(attachmentCount.toString()) : null, + trailing: LinkIcon( + text: attachmentCount > 0 ? attachmentCount.toString() : null, + ), onTap: () { Navigator.push( context, diff --git a/lib/widget/order/purchase_order_list.dart b/lib/widget/order/purchase_order_list.dart index 033e3066..4c1b3633 100644 --- a/lib/widget/order/purchase_order_list.dart +++ b/lib/widget/order/purchase_order_list.dart @@ -4,6 +4,7 @@ import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; import "package:inventree/inventree/company.dart"; import "package:inventree/inventree/model.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/paginator.dart"; import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/l10.dart"; @@ -173,11 +174,9 @@ class _PaginatedPurchaseOrderListState leading: supplier == null ? null : InvenTreeAPI().getThumbnail(supplier.thumbnail), - trailing: Text( + trailing: LargeText( InvenTreeAPI().PurchaseOrderStatus.label(order.status), - style: TextStyle( - color: InvenTreeAPI().PurchaseOrderStatus.color(order.status), - ), + color: InvenTreeAPI().PurchaseOrderStatus.color(order.status), ), onTap: () async { order.goToDetailPage(context); diff --git a/lib/widget/order/sales_order_detail.dart b/lib/widget/order/sales_order_detail.dart index 6318419f..bc23961e 100644 --- a/lib/widget/order/sales_order_detail.dart +++ b/lib/widget/order/sales_order_detail.dart @@ -6,6 +6,7 @@ import "package:inventree/barcode/sales_order.dart"; import "package:inventree/inventree/company.dart"; import "package:inventree/inventree/sales_order.dart"; import "package:inventree/preferences.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/order/so_extra_line_list.dart"; import "package:inventree/widget/order/so_line_list.dart"; import "package:inventree/widget/order/so_shipment_list.dart"; @@ -323,11 +324,9 @@ class _SalesOrderDetailState extends RefreshableState { title: Text(widget.order.reference), subtitle: Text(widget.order.description), leading: customer == null ? null : api.getThumbnail(customer.thumbnail), - trailing: Text( + trailing: LargeText( api.SalesOrderStatus.label(widget.order.status), - style: TextStyle( - color: api.SalesOrderStatus.color(widget.order.status), - ), + color: api.SalesOrderStatus.color(widget.order.status), ), ), ); @@ -356,6 +355,7 @@ class _SalesOrderDetailState extends RefreshableState { title: Text(L10().customer), subtitle: Text(customer.name), leading: Icon(TablerIcons.user, color: COLOR_ACTION), + trailing: LinkIcon(), onTap: () { customer.goToDetailPage(context); }, @@ -367,7 +367,7 @@ class _SalesOrderDetailState extends RefreshableState { tiles.add( ListTile( title: Text(L10().customerReference), - trailing: Text(widget.order.customerReference), + trailing: LargeText(widget.order.customerReference), leading: Icon(TablerIcons.hash), ), ); @@ -375,6 +375,24 @@ class _SalesOrderDetailState extends RefreshableState { Color lineColor = widget.order.complete ? COLOR_SUCCESS : COLOR_WARNING; + // Shipment progress + if (widget.order.shipmentCount > 0) { + tiles.add( + ListTile( + title: Text(L10().shipments), + subtitle: ProgressBar( + widget.order.completedShipmentCount.toDouble(), + maximum: widget.order.shipmentCount.toDouble(), + ), + leading: Icon(TablerIcons.truck_delivery), + trailing: LargeText( + "${widget.order.completedShipmentCount} / ${widget.order.shipmentCount}", + color: lineColor, + ), + ), + ); + } + tiles.add( ListTile( title: Text(L10().lineItems), @@ -383,9 +401,9 @@ class _SalesOrderDetailState extends RefreshableState { maximum: widget.order.lineItemCount.toDouble(), ), leading: Icon(TablerIcons.clipboard_check), - trailing: Text( + trailing: LargeText( "${widget.order.completedLineItemCount} / ${widget.order.lineItemCount}", - style: TextStyle(color: lineColor), + color: lineColor, ), ), ); @@ -395,7 +413,7 @@ class _SalesOrderDetailState extends RefreshableState { ListTile( title: Text(L10().extraLineItems), leading: Icon(TablerIcons.clipboard_list, color: COLOR_ACTION), - trailing: Text(extraLineCount.toString()), + trailing: LinkIcon(text: extraLineCount.toString()), onTap: () => { Navigator.push( context, @@ -410,31 +428,13 @@ class _SalesOrderDetailState extends RefreshableState { ), ); - // Shipment progress - if (widget.order.shipmentCount > 0) { - tiles.add( - ListTile( - title: Text(L10().shipments), - subtitle: ProgressBar( - widget.order.completedShipmentCount.toDouble(), - maximum: widget.order.shipmentCount.toDouble(), - ), - leading: Icon(TablerIcons.truck_delivery), - trailing: Text( - "${widget.order.completedShipmentCount} / ${widget.order.shipmentCount}", - style: TextStyle(color: lineColor), - ), - ), - ); - } - // TODO: total price if (widget.order.startDate.isNotEmpty) { tiles.add( ListTile( title: Text(L10().startDate), - trailing: Text(widget.order.startDate), + trailing: LargeText(widget.order.startDate), leading: Icon(TablerIcons.calendar), ), ); @@ -444,7 +444,7 @@ class _SalesOrderDetailState extends RefreshableState { tiles.add( ListTile( title: Text(L10().targetDate), - trailing: Text(widget.order.targetDate), + trailing: LargeText(widget.order.targetDate), leading: Icon(TablerIcons.calendar), ), ); @@ -454,7 +454,7 @@ class _SalesOrderDetailState extends RefreshableState { tiles.add( ListTile( title: Text(L10().completionDate), - trailing: Text(widget.order.shipmentDate), + trailing: LargeText(widget.order.shipmentDate), leading: Icon(TablerIcons.calendar), ), ); @@ -471,7 +471,7 @@ class _SalesOrderDetailState extends RefreshableState { ? TablerIcons.users : TablerIcons.user, ), - trailing: Text(widget.order.responsibleName), + trailing: LargeText(widget.order.responsibleName), ), ); } @@ -481,6 +481,7 @@ class _SalesOrderDetailState extends RefreshableState { ListTile( title: Text(L10().notes), leading: Icon(TablerIcons.note, color: COLOR_ACTION), + trailing: LinkIcon(), onTap: () { Navigator.push( context, @@ -495,7 +496,9 @@ class _SalesOrderDetailState extends RefreshableState { ListTile( title: Text(L10().attachments), leading: Icon(TablerIcons.file, color: COLOR_ACTION), - trailing: attachmentCount > 0 ? Text(attachmentCount.toString()) : null, + trailing: LinkIcon( + text: attachmentCount > 0 ? attachmentCount.toString() : null, + ), onTap: () { Navigator.push( context, @@ -519,8 +522,8 @@ class _SalesOrderDetailState extends RefreshableState { List getTabIcons(BuildContext context) { return [ Tab(text: L10().details), - Tab(text: L10().lineItems), Tab(text: L10().shipments), + Tab(text: L10().lineItems), ]; } @@ -528,8 +531,8 @@ class _SalesOrderDetailState extends RefreshableState { List getTabs(BuildContext context) { return [ ListView(children: orderTiles(context)), - PaginatedSOLineList({"order": widget.order.pk.toString()}), PaginatedSOShipmentList({"order": widget.order.pk.toString()}), + PaginatedSOLineList({"order": widget.order.pk.toString()}), ]; } } diff --git a/lib/widget/order/sales_order_list.dart b/lib/widget/order/sales_order_list.dart index 089363ea..2c0ff4a9 100644 --- a/lib/widget/order/sales_order_list.dart +++ b/lib/widget/order/sales_order_list.dart @@ -2,6 +2,7 @@ import "package:flutter/material.dart"; import "package:flutter_speed_dial/flutter_speed_dial.dart"; import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; import "package:inventree/inventree/sales_order.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/paginator.dart"; import "package:inventree/widget/refreshable_state.dart"; @@ -155,11 +156,9 @@ class _PaginatedSalesOrderListState leading: customer == null ? null : InvenTreeAPI().getThumbnail(customer.thumbnail), - trailing: Text( + trailing: LargeText( InvenTreeAPI().SalesOrderStatus.label(order.status), - style: TextStyle( - color: InvenTreeAPI().SalesOrderStatus.color(order.status), - ), + color: InvenTreeAPI().SalesOrderStatus.color(order.status), ), onTap: () async { order.goToDetailPage(context); diff --git a/lib/widget/order/so_extra_line_list.dart b/lib/widget/order/so_extra_line_list.dart index 0ed13a54..06521e6c 100644 --- a/lib/widget/order/so_extra_line_list.dart +++ b/lib/widget/order/so_extra_line_list.dart @@ -6,6 +6,7 @@ import "package:inventree/l10.dart"; import "package:inventree/inventree/model.dart"; import "package:inventree/inventree/sales_order.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/paginator.dart"; import "package:inventree/widget/refreshable_state.dart"; @@ -112,7 +113,7 @@ class _PaginatedSOExtraLineListState return ListTile( title: Text(line.reference), subtitle: Text(line.description), - trailing: Text(line.quantity.toString()), + trailing: LargeText(line.quantity.toString()), onTap: () { line.goToDetailPage(context).then((_) { refresh(); diff --git a/lib/widget/order/so_line_detail.dart b/lib/widget/order/so_line_detail.dart index f2f61ad8..ae0d3025 100644 --- a/lib/widget/order/so_line_detail.dart +++ b/lib/widget/order/so_line_detail.dart @@ -10,6 +10,7 @@ import "package:inventree/barcode/sales_order.dart"; import "package:inventree/inventree/part.dart"; import "package:inventree/inventree/sales_order.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/progress.dart"; @@ -172,7 +173,7 @@ class _SOLineDetailWidgetState extends RefreshableState { title: Text(L10().part), subtitle: Text(widget.item.partName), leading: Icon(TablerIcons.box, color: COLOR_ACTION), - trailing: api.getThumbnail(widget.item.partImage), + trailing: LinkIcon(image: api.getThumbnail(widget.item.partImage)), onTap: () async { showLoadingOverlay(); var part = await InvenTreePart().get(widget.item.partId); @@ -190,7 +191,7 @@ class _SOLineDetailWidgetState extends RefreshableState { ListTile( title: Text(L10().availableStock), leading: Icon(TablerIcons.packages), - trailing: Text(simpleNumberString(widget.item.availableStock)), + trailing: LargeText(simpleNumberString(widget.item.availableStock)), ), ); @@ -200,11 +201,9 @@ class _SOLineDetailWidgetState extends RefreshableState { leading: Icon(TablerIcons.clipboard_check), title: Text(L10().allocated), subtitle: ProgressBar(widget.item.allocatedRatio), - trailing: Text( + trailing: LargeText( widget.item.allocatedString, - style: TextStyle( - color: widget.item.isAllocated ? COLOR_SUCCESS : COLOR_WARNING, - ), + color: widget.item.isAllocated ? COLOR_SUCCESS : COLOR_WARNING, ), ), ); @@ -214,11 +213,9 @@ class _SOLineDetailWidgetState extends RefreshableState { ListTile( title: Text(L10().shipped), subtitle: ProgressBar(widget.item.progressRatio), - trailing: Text( + trailing: LargeText( widget.item.progressString, - style: TextStyle( - color: widget.item.isComplete ? COLOR_SUCCESS : COLOR_WARNING, - ), + color: widget.item.isComplete ? COLOR_SUCCESS : COLOR_WARNING, ), leading: Icon(TablerIcons.truck), ), diff --git a/lib/widget/order/so_line_list.dart b/lib/widget/order/so_line_list.dart index 2530d3e1..acadfeb1 100644 --- a/lib/widget/order/so_line_list.dart +++ b/lib/widget/order/so_line_list.dart @@ -1,5 +1,6 @@ import "package:flutter/material.dart"; import "package:inventree/l10.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/order/so_line_detail.dart"; import "package:inventree/widget/paginator.dart"; import "package:inventree/inventree/model.dart"; @@ -67,11 +68,9 @@ class _PaginatedSOLineListState title: Text(part.name), subtitle: Text(part.description), leading: InvenTreeAPI().getThumbnail(part.thumbnail), - trailing: Text( + trailing: LargeText( item.progressString, - style: TextStyle( - color: item.isComplete ? COLOR_SUCCESS : COLOR_WARNING, - ), + color: item.isComplete ? COLOR_SUCCESS : COLOR_WARNING, ), onTap: () async { showLoadingOverlay(); diff --git a/lib/widget/order/so_shipment_list.dart b/lib/widget/order/so_shipment_list.dart index a6c14723..126e247e 100644 --- a/lib/widget/order/so_shipment_list.dart +++ b/lib/widget/order/so_shipment_list.dart @@ -2,6 +2,7 @@ import "package:flutter/material.dart"; import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; import "package:inventree/app_colors.dart"; import "package:inventree/inventree/sales_order.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/paginator.dart"; import "package:inventree/inventree/model.dart"; @@ -56,7 +57,9 @@ class _PaginatedSOShipmentListState leading: shipment.shipped ? Icon(TablerIcons.calendar_check, color: COLOR_SUCCESS) : Icon(TablerIcons.calendar_cancel, color: COLOR_WARNING), - trailing: shipment.shipped ? Text(shipment.shipment_date ?? "") : null, + trailing: shipment.shipped + ? LargeText(shipment.shipment_date ?? "") + : null, ); } } diff --git a/lib/widget/part/category_display.dart b/lib/widget/part/category_display.dart index 19138c95..bb9464be 100644 --- a/lib/widget/part/category_display.dart +++ b/lib/widget/part/category_display.dart @@ -6,6 +6,7 @@ import "package:inventree/app_colors.dart"; import "package:inventree/l10.dart"; import "package:inventree/inventree/part.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/part/category_list.dart"; import "package:inventree/widget/part/part_list.dart"; @@ -144,6 +145,7 @@ class _CategoryDisplayState extends RefreshableState { title: Text(L10().parentCategory), subtitle: Text("${widget.category?.parentPathString}"), leading: Icon(TablerIcons.arrow_move_up, color: COLOR_ACTION), + trailing: LinkIcon(), onTap: () async { int parentId = widget.category?.parentId ?? -1; diff --git a/lib/widget/part/category_list.dart b/lib/widget/part/category_list.dart index 41442d97..ced2783b 100644 --- a/lib/widget/part/category_list.dart +++ b/lib/widget/part/category_list.dart @@ -2,6 +2,7 @@ import "package:flutter/material.dart"; import "package:inventree/inventree/model.dart"; import "package:inventree/inventree/part.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/paginator.dart"; import "package:inventree/widget/refreshable_state.dart"; @@ -96,7 +97,7 @@ class _PaginatedPartCategoryListState return ListTile( title: Text(category.name), subtitle: Text(category.pathstring), - trailing: Text("${category.partcount}"), + trailing: LargeText("${category.partcount}", size: 14), leading: category.customIcon == null ? null : Icon(category.customIcon), onTap: () { category.goToDetailPage(context); diff --git a/lib/widget/part/part_detail.dart b/lib/widget/part/part_detail.dart index fa8e4505..5d59aeda 100644 --- a/lib/widget/part/part_detail.dart +++ b/lib/widget/part/part_detail.dart @@ -14,6 +14,7 @@ import "package:inventree/labels.dart"; import "package:inventree/preferences.dart"; import "package:inventree/widget/attachment_widget.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/part/bom_list.dart"; import "package:inventree/widget/part/part_list.dart"; import "package:inventree/widget/notes_widget.dart"; @@ -334,6 +335,7 @@ class _PartDisplayState extends RefreshableState { title: Text(L10().templatePart), subtitle: Text(parentPart!.fullname), leading: api.getImage(parentPart!.thumbnail, width: 32, height: 32), + trailing: LinkIcon(), onTap: () { parentPart?.goToDetailPage(context); }, @@ -348,6 +350,7 @@ class _PartDisplayState extends RefreshableState { title: Text(L10().partCategory), subtitle: Text("${part.categoryName}"), leading: Icon(TablerIcons.sitemap, color: COLOR_ACTION), + trailing: LinkIcon(), onTap: () async { if (part.categoryId > 0) { showLoadingOverlay(); @@ -385,7 +388,7 @@ class _PartDisplayState extends RefreshableState { ListTile( title: Text(L10().variants), leading: Icon(TablerIcons.versions, color: COLOR_ACTION), - trailing: Text(variantCount.toString()), + trailing: LinkIcon(text: variantCount.toString()), onTap: () { Navigator.push( context, @@ -405,10 +408,7 @@ class _PartDisplayState extends RefreshableState { title: Text(L10().availableStock), subtitle: Text(L10().stockDetails), leading: Icon(TablerIcons.packages), - trailing: Text( - part.stockString(), - style: TextStyle(fontWeight: FontWeight.bold), - ), + trailing: LargeText(part.stockString()), ), ); @@ -422,11 +422,11 @@ class _PartDisplayState extends RefreshableState { tiles.add( ListTile( title: Text(L10().partPricing), - leading: Icon(TablerIcons.currency_dollar, color: COLOR_ACTION), - trailing: Text( + subtitle: Text( pricing.isNotEmpty ? pricing : L10().noPricingAvailable, - style: TextStyle(fontWeight: FontWeight.bold), ), + leading: Icon(TablerIcons.currency_dollar, color: COLOR_ACTION), + trailing: LinkIcon(), onTap: () { Navigator.push( context, @@ -448,7 +448,7 @@ class _PartDisplayState extends RefreshableState { title: Text(L10().onOrder), subtitle: Text(L10().onOrderDetails), leading: Icon(TablerIcons.shopping_cart), - trailing: Text("${part.onOrderString}"), + trailing: LargeText("${part.onOrderString}"), onTap: () { // TODO - Order views }, @@ -463,7 +463,7 @@ class _PartDisplayState extends RefreshableState { ListTile( title: Text(L10().billOfMaterials), leading: Icon(TablerIcons.list_tree, color: COLOR_ACTION), - trailing: Text(bomCount.toString()), + trailing: LinkIcon(text: bomCount.toString()), onTap: () { Navigator.push( context, @@ -482,9 +482,9 @@ class _PartDisplayState extends RefreshableState { ListTile( title: Text(L10().building), leading: Icon(TablerIcons.tools), - trailing: Text("${simpleNumberString(part.building)}"), + trailing: LargeText("${simpleNumberString(part.building)}"), onTap: () { - // TODO + // TODO: List of active build orders? }, ), ); @@ -498,7 +498,7 @@ class _PartDisplayState extends RefreshableState { title: Text(L10().usedIn), subtitle: Text(L10().usedInDetails), leading: Icon(TablerIcons.stack_2, color: COLOR_ACTION), - trailing: Text(usedInCount.toString()), + trailing: LinkIcon(text: usedInCount.toString()), onTap: () { Navigator.push( context, @@ -543,9 +543,9 @@ class _PartDisplayState extends RefreshableState { title: Text(L10().usedIn), subtitle: Text(L10().usedInDetails), leading: Icon(TablerIcons.sitemap), - trailing: Text("${part.usedInCount}"), + trailing: LargeText("${part.usedInCount}"), onTap: () { - // TODO + // TODO: Show assemblies which use this part }, ), ); @@ -557,7 +557,7 @@ class _PartDisplayState extends RefreshableState { ListTile( title: Text(L10().suppliers), leading: Icon(TablerIcons.building_factory, color: COLOR_ACTION), - trailing: Text("${part.supplierCount}"), + trailing: LinkIcon(text: "${part.supplierCount}"), onTap: () { Navigator.push( context, @@ -577,7 +577,7 @@ class _PartDisplayState extends RefreshableState { ListTile( title: Text(L10().notes), leading: Icon(TablerIcons.note, color: COLOR_ACTION), - trailing: Text(""), + trailing: LinkIcon(), onTap: () { Navigator.push( context, @@ -591,7 +591,9 @@ class _PartDisplayState extends RefreshableState { ListTile( title: Text(L10().attachments), leading: Icon(TablerIcons.file, color: COLOR_ACTION), - trailing: attachmentCount > 0 ? Text(attachmentCount.toString()) : null, + trailing: LinkIcon( + text: attachmentCount > 0 ? attachmentCount.toString() : null, + ), onTap: () { Navigator.push( context, diff --git a/lib/widget/part/part_list.dart b/lib/widget/part/part_list.dart index e4545229..3f219b57 100644 --- a/lib/widget/part/part_list.dart +++ b/lib/widget/part/part_list.dart @@ -5,6 +5,7 @@ import "package:inventree/l10.dart"; import "package:inventree/inventree/model.dart"; import "package:inventree/inventree/part.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/paginator.dart"; import "package:inventree/widget/refreshable_state.dart"; @@ -121,10 +122,7 @@ class _PaginatedPartListState extends PaginatedSearchState { return ListTile( title: Text(part.fullname), subtitle: Text(part.description), - trailing: Text( - part.stockString(), - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), - ), + trailing: LargeText(part.stockString()), leading: InvenTreeAPI().getThumbnail(part.thumbnail), onTap: () { part.goToDetailPage(context); diff --git a/lib/widget/refreshable_state.dart b/lib/widget/refreshable_state.dart index cd53b829..d9c5ad59 100644 --- a/lib/widget/refreshable_state.dart +++ b/lib/widget/refreshable_state.dart @@ -42,7 +42,7 @@ mixin BaseWidgetProperties { // Override getTiles to replace the internal context return ListView( physics: AlwaysScrollableScrollPhysics(), - children: getTiles(context), + children: [Divider(), ...getTiles(context)], ); } diff --git a/lib/widget/stock/location_display.dart b/lib/widget/stock/location_display.dart index 8c1a681e..7719724a 100644 --- a/lib/widget/stock/location_display.dart +++ b/lib/widget/stock/location_display.dart @@ -10,6 +10,7 @@ import "package:inventree/l10.dart"; import "package:inventree/inventree/stock.dart"; import "package:inventree/preferences.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/stock/location_list.dart"; import "package:inventree/widget/progress.dart"; @@ -341,6 +342,7 @@ class _LocationDisplayState extends RefreshableState { title: Text(L10().parentLocation), subtitle: Text("${location!.parentPathString}"), leading: Icon(TablerIcons.arrow_move_up, color: COLOR_ACTION), + trailing: LinkIcon(), onTap: () async { int parentId = location?.parentId ?? -1; diff --git a/lib/widget/stock/location_list.dart b/lib/widget/stock/location_list.dart index 1fc8032b..a27182d1 100644 --- a/lib/widget/stock/location_list.dart +++ b/lib/widget/stock/location_list.dart @@ -2,6 +2,7 @@ import "package:flutter/material.dart"; import "package:inventree/inventree/model.dart"; import "package:inventree/inventree/stock.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/paginator.dart"; import "package:inventree/widget/refreshable_state.dart"; @@ -86,7 +87,7 @@ class _PaginatedStockLocationListState return ListTile( title: Text(location.name), subtitle: Text(location.pathstring), - trailing: Text("${location.itemcount}"), + trailing: LargeText("${location.itemcount}", size: 14), leading: location.customIcon == null ? null : Icon(location.customIcon), onTap: () { location.goToDetailPage(context); diff --git a/lib/widget/stock/stock_detail.dart b/lib/widget/stock/stock_detail.dart index c6996bca..e91bd989 100644 --- a/lib/widget/stock/stock_detail.dart +++ b/lib/widget/stock/stock_detail.dart @@ -18,9 +18,9 @@ import "package:inventree/inventree/company.dart"; import "package:inventree/inventree/stock.dart"; import "package:inventree/inventree/part.dart"; -import "package:inventree/widget/company/supplier_part_detail.dart"; import "package:inventree/widget/dialogs.dart"; import "package:inventree/widget/attachment_widget.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/progress.dart"; import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/snacks.dart"; @@ -490,14 +490,11 @@ class _StockItemDisplayState extends RefreshableState { Widget? trailing; if (!widget.item.isInStock) { - trailing = Text(L10().unavailable, style: TextStyle(color: COLOR_DANGER)); + trailing = LargeText(L10().unavailable, color: COLOR_DANGER); } else if (!widget.item.isSerialized()) { - trailing = Text( + trailing = LargeText( widget.item.quantityString(), - style: TextStyle( - fontSize: 20, - color: api.StockStatus.color(widget.item.status), - ), + color: api.StockStatus.color(widget.item.status), ); } @@ -518,7 +515,7 @@ class _StockItemDisplayState extends RefreshableState { } } }, - //trailing: Text(item.serialOrQuantityDisplay()), + //trailing: LargeText(item.serialOrQuantityDisplay()), ), ); } @@ -546,6 +543,7 @@ class _StockItemDisplayState extends RefreshableState { title: Text(L10().stockLocation), subtitle: Text("${widget.item.locationPathString}"), leading: Icon(TablerIcons.location, color: COLOR_ACTION), + trailing: LinkIcon(), onTap: () async { if (widget.item.locationId > 0) { showLoadingOverlay(); @@ -587,7 +585,7 @@ class _StockItemDisplayState extends RefreshableState { ? Text(L10().quantityAvailable) : Text(L10().quantity), leading: Icon(TablerIcons.packages), - trailing: Text("${widget.item.quantityString()}"), + trailing: LargeText("${widget.item.quantityString()}"), ), ); } @@ -613,9 +611,9 @@ class _StockItemDisplayState extends RefreshableState { ListTile( title: Text(L10().status), leading: Icon(TablerIcons.help_circle), - trailing: Text( + trailing: LargeText( api.StockStatus.label(widget.item.status), - style: TextStyle(color: api.StockStatus.color(widget.item.status)), + color: api.StockStatus.color(widget.item.status), ), ), ); @@ -627,10 +625,7 @@ class _StockItemDisplayState extends RefreshableState { title: Text(L10().supplierPart), subtitle: Text(widget.item.supplierSKU), leading: Icon(TablerIcons.building, color: COLOR_ACTION), - trailing: InvenTreeAPI().getThumbnail( - widget.item.supplierImage, - hideIfNull: true, - ), + trailing: LinkIcon(), onTap: () async { showLoadingOverlay(); var sp = await InvenTreeSupplierPart().get( @@ -638,12 +633,7 @@ class _StockItemDisplayState extends RefreshableState { ); hideLoadingOverlay(); if (sp is InvenTreeSupplierPart) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SupplierPartDetailWidget(sp), - ), - ); + sp.goToDetailPage(context); } }, ), @@ -667,9 +657,11 @@ class _StockItemDisplayState extends RefreshableState { tiles.add( ListTile( title: Text(L10().salesOrder), - subtitle: Text(salesOrder?.description ?? ""), + subtitle: Text( + salesOrder?.reference ?? salesOrder?.description ?? "", + ), leading: Icon(TablerIcons.truck_delivery, color: COLOR_ACTION), - trailing: Text(salesOrder?.reference ?? ""), + trailing: LinkIcon(), onTap: () { salesOrder?.goToDetailPage(context); }, @@ -681,9 +673,9 @@ class _StockItemDisplayState extends RefreshableState { tiles.add( ListTile( title: Text(L10().customer), - subtitle: Text(customer?.description ?? ""), + subtitle: Text("${customer?.name} - ${customer?.description}"), leading: Icon(TablerIcons.building_store, color: COLOR_ACTION), - trailing: Text(customer?.name ?? ""), + trailing: LinkIcon(), onTap: () { customer?.goToDetailPage(context); }, @@ -741,7 +733,7 @@ class _StockItemDisplayState extends RefreshableState { tiles.add( ListTile( title: Text(L10().lastUpdated), - subtitle: Text(widget.item.updatedDateString), + trailing: LargeText(widget.item.updatedDateString), leading: Icon(TablerIcons.calendar), ), ); @@ -775,7 +767,7 @@ class _StockItemDisplayState extends RefreshableState { ListTile( title: Text(L10().testResults), leading: Icon(TablerIcons.list_check, color: COLOR_ACTION), - trailing: Text("${widget.item.testResultCount}"), + trailing: LinkIcon(text: "${widget.item.testResultCount}"), onTap: () { Navigator.push( context, @@ -795,7 +787,7 @@ class _StockItemDisplayState extends RefreshableState { ListTile( title: Text(L10().purchasePrice), leading: Icon(TablerIcons.currency_dollar), - trailing: Text( + trailing: LargeText( renderCurrency( widget.item.purchasePrice, widget.item.purchasePriceCurrency, @@ -812,7 +804,7 @@ class _StockItemDisplayState extends RefreshableState { ListTile( title: Text(L10().history), leading: Icon(TablerIcons.history, color: COLOR_ACTION), - trailing: Text("${widget.item.trackingItemCount}"), + trailing: LinkIcon(text: "${widget.item.trackingItemCount}"), onTap: () { Navigator.push( context, @@ -832,6 +824,7 @@ class _StockItemDisplayState extends RefreshableState { ListTile( title: Text(L10().notes), leading: Icon(TablerIcons.note, color: COLOR_ACTION), + trailing: LinkIcon(), onTap: () { Navigator.push( context, @@ -845,7 +838,9 @@ class _StockItemDisplayState extends RefreshableState { ListTile( title: Text(L10().attachments), leading: Icon(TablerIcons.file, color: COLOR_ACTION), - trailing: attachmentCount > 0 ? Text(attachmentCount.toString()) : null, + trailing: LinkIcon( + text: attachmentCount > 0 ? attachmentCount.toString() : null, + ), onTap: () { Navigator.push( context, diff --git a/lib/widget/stock/stock_list.dart b/lib/widget/stock/stock_list.dart index e65f7aba..8e6e89d1 100644 --- a/lib/widget/stock/stock_list.dart +++ b/lib/widget/stock/stock_list.dart @@ -2,6 +2,7 @@ import "package:flutter/material.dart"; import "package:inventree/inventree/model.dart"; import "package:inventree/inventree/stock.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/paginator.dart"; import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/l10.dart"; @@ -130,16 +131,10 @@ class _PaginatedStockItemListState title: Text("${item.partName}"), subtitle: Text(item.locationPathString), leading: InvenTreeAPI().getThumbnail(item.partThumbnail), - trailing: SizedBox( - width: 48, - child: Text( - "${item.displayQuantity}", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: InvenTreeAPI().StockStatus.color(item.status), - ), - ), + trailing: LargeText( + item.displayQuantity, + size: 14, + color: InvenTreeAPI().StockStatus.color(item.status), ), onTap: () { item.goToDetailPage(context);