Refactor
This commit is contained in:
parent
ea16feae8f
commit
41feda26b8
|
|
@ -12,11 +12,13 @@ class ViewScaffold extends StatelessWidget {
|
||||||
const ViewScaffold({
|
const ViewScaffold({
|
||||||
@required this.body,
|
@required this.body,
|
||||||
@required this.entity,
|
@required this.entity,
|
||||||
|
this.title,
|
||||||
this.floatingActionButton,
|
this.floatingActionButton,
|
||||||
this.appBarBottom,
|
this.appBarBottom,
|
||||||
});
|
});
|
||||||
|
|
||||||
final BaseEntity entity;
|
final BaseEntity entity;
|
||||||
|
final String title;
|
||||||
final Widget body;
|
final Widget body;
|
||||||
final Widget floatingActionButton;
|
final Widget floatingActionButton;
|
||||||
final Widget appBarBottom;
|
final Widget appBarBottom;
|
||||||
|
|
@ -34,7 +36,10 @@ class ViewScaffold extends StatelessWidget {
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
automaticallyImplyLeading: isMobile(context),
|
automaticallyImplyLeading: isMobile(context),
|
||||||
title: EntityStateTitle(entity: entity),
|
title: EntityStateTitle(
|
||||||
|
entity: entity,
|
||||||
|
title: title,
|
||||||
|
),
|
||||||
bottom: appBarBottom,
|
bottom: appBarBottom,
|
||||||
actions: entity.isNew
|
actions: entity.isNew
|
||||||
? []
|
? []
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:invoiceninja_flutter/constants.dart';
|
import 'package:invoiceninja_flutter/constants.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/company_gateway/company_gateway_screen.dart';
|
|
||||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,9 @@ import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/document/document_actions.dart';
|
import 'package:invoiceninja_flutter/redux/document/document_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/expense/expense_actions.dart';
|
import 'package:invoiceninja_flutter/redux/expense/expense_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/expense/expense_screen.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/expense/view/expense_view.dart';
|
import 'package:invoiceninja_flutter/ui/expense/view/expense_view.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,8 @@ import 'package:invoiceninja_flutter/ui/app/edit_scaffold.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
|
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/group/edit/group_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/group/edit/group_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/buttons/action_flat_button.dart';
|
|
||||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
|
||||||
|
|
||||||
class GroupEdit extends StatefulWidget {
|
class GroupEdit extends StatefulWidget {
|
||||||
const GroupEdit({
|
const GroupEdit({
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:invoiceninja_flutter/constants.dart';
|
import 'package:invoiceninja_flutter/constants.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/group/group_screen.dart';
|
|
||||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import 'package:invoiceninja_flutter/ui/app/buttons/edit_icon_button.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart';
|
import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/view_scaffold.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_documents.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_documents.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_overview.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_overview.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_vm.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_vm.dart';
|
||||||
|
|
@ -41,99 +42,18 @@ class _InvoiceViewState extends State<InvoiceView>
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final viewModel = widget.viewModel;
|
final viewModel = widget.viewModel;
|
||||||
|
|
||||||
return WillPopScope(
|
|
||||||
onWillPop: () async {
|
|
||||||
viewModel.onBackPressed();
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
child: Scaffold(
|
|
||||||
appBar: _CustomAppBar(
|
|
||||||
viewModel: viewModel,
|
|
||||||
controller: _controller,
|
|
||||||
),
|
|
||||||
body: Builder(
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return RefreshIndicator(
|
|
||||||
onRefresh: () => viewModel.onRefreshed(context),
|
|
||||||
child: CustomTabBarView(
|
|
||||||
viewModel: viewModel,
|
|
||||||
controller: _controller,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CustomTabBarView extends StatefulWidget {
|
|
||||||
const CustomTabBarView({
|
|
||||||
@required this.viewModel,
|
|
||||||
@required this.controller,
|
|
||||||
});
|
|
||||||
|
|
||||||
final EntityViewVM viewModel;
|
|
||||||
final TabController controller;
|
|
||||||
|
|
||||||
@override
|
|
||||||
_CustomTabBarViewState createState() => _CustomTabBarViewState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _CustomTabBarViewState extends State<CustomTabBarView> {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final viewModel = widget.viewModel;
|
|
||||||
|
|
||||||
return TabBarView(
|
|
||||||
controller: widget.controller,
|
|
||||||
children: <Widget>[
|
|
||||||
RefreshIndicator(
|
|
||||||
onRefresh: () => viewModel.onRefreshed(context),
|
|
||||||
child: InvoiceOverview(viewModel: viewModel),
|
|
||||||
),
|
|
||||||
RefreshIndicator(
|
|
||||||
onRefresh: () => viewModel.onRefreshed(context),
|
|
||||||
child: InvoiceViewDocuments(
|
|
||||||
viewModel: viewModel, invoice: viewModel.invoice),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|
||||||
const _CustomAppBar({
|
|
||||||
@required this.viewModel,
|
|
||||||
@required this.controller,
|
|
||||||
});
|
|
||||||
|
|
||||||
final EntityViewVM viewModel;
|
|
||||||
final TabController controller;
|
|
||||||
|
|
||||||
@override
|
|
||||||
final Size preferredSize = const Size(double.infinity, kToolbarHeight * 2);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final localization = AppLocalization.of(context);
|
|
||||||
final invoice = viewModel.invoice;
|
final invoice = viewModel.invoice;
|
||||||
final userCompany = viewModel.state.userCompany;
|
final localization = AppLocalization.of(context);
|
||||||
final client = viewModel.client;
|
|
||||||
final documentState = viewModel.state.documentState;
|
final documentState = viewModel.state.documentState;
|
||||||
final documents = memoizedInvoiceDocumentsSelector(
|
final documents = memoizedInvoiceDocumentsSelector(
|
||||||
documentState.map, viewModel.state.expenseState.map, invoice);
|
documentState.map, viewModel.state.expenseState.map, invoice);
|
||||||
|
|
||||||
return AppBar(
|
return ViewScaffold(
|
||||||
automaticallyImplyLeading: isMobile(context),
|
entity: invoice,
|
||||||
title: EntityStateTitle(
|
title:
|
||||||
entity: invoice,
|
'${localization.invoice} ${invoice.number ?? '• ${localization.pending}'}',
|
||||||
title:
|
appBarBottom: TabBar(
|
||||||
'${localization.invoice} ${invoice.number ?? '• ${localization.pending}'}',
|
controller: _controller,
|
||||||
),
|
|
||||||
bottom: TabBar(
|
|
||||||
controller: controller,
|
|
||||||
tabs: [
|
tabs: [
|
||||||
Tab(
|
Tab(
|
||||||
text: localization.overview,
|
text: localization.overview,
|
||||||
|
|
@ -145,23 +65,27 @@ class _CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: invoice.isNew
|
body: Builder(
|
||||||
? []
|
builder: (BuildContext context) {
|
||||||
: [
|
return RefreshIndicator(
|
||||||
userCompany.canEditEntity(invoice)
|
onRefresh: () => viewModel.onRefreshed(context),
|
||||||
? EditIconButton(
|
child: TabBarView(
|
||||||
isVisible: !invoice.isDeleted,
|
controller: _controller,
|
||||||
onPressed: () => viewModel.onEditPressed(context),
|
children: <Widget>[
|
||||||
)
|
RefreshIndicator(
|
||||||
: Container(),
|
onRefresh: () => viewModel.onRefreshed(context),
|
||||||
ActionMenuButton(
|
child: InvoiceOverview(viewModel: viewModel),
|
||||||
entityActions: invoice.getActions(
|
),
|
||||||
client: client, userCompany: userCompany),
|
RefreshIndicator(
|
||||||
isSaving: viewModel.isSaving,
|
onRefresh: () => viewModel.onRefreshed(context),
|
||||||
entity: invoice,
|
child: InvoiceViewDocuments(
|
||||||
onSelected: viewModel.onActionSelected,
|
viewModel: viewModel, invoice: viewModel.invoice),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,9 @@ import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/document/document_actions.dart';
|
import 'package:invoiceninja_flutter/redux/document/document_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_screen.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/buttons/edit_icon_button.dart';
|
import 'package:invoiceninja_flutter/ui/app/buttons/edit_icon_button.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_state_title.dart';
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_state_title.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/entity_header.dart';
|
import 'package:invoiceninja_flutter/ui/app/entity_header.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/view_scaffold.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/product/view/product_view_vm.dart';
|
import 'package:invoiceninja_flutter/ui/product/view/product_view_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
|
@ -81,75 +82,31 @@ class _ProductViewState extends State<ProductView>
|
||||||
value: product.customValue2);
|
value: product.customValue2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return WillPopScope(
|
return ViewScaffold(
|
||||||
onWillPop: () async {
|
entity: product,
|
||||||
viewModel.onBackPressed();
|
body: ListView(
|
||||||
return true;
|
children: <Widget>[
|
||||||
},
|
EntityHeader(
|
||||||
child: Scaffold(
|
label: localization.price,
|
||||||
appBar: _CustomAppBar(
|
value: formatNumber(product.price, context),
|
||||||
viewModel: viewModel,
|
secondLabel: localization.cost,
|
||||||
),
|
secondValue: company.enableProductCost
|
||||||
body: ListView(
|
? formatNumber(product.cost, context)
|
||||||
children: <Widget>[
|
: null,
|
||||||
EntityHeader(
|
),
|
||||||
label: localization.price,
|
FieldGrid(fields),
|
||||||
value: formatNumber(product.price, context),
|
Divider(
|
||||||
secondLabel: localization.cost,
|
height: 1.0,
|
||||||
secondValue: company.enableProductCost
|
),
|
||||||
? formatNumber(product.cost, context)
|
Padding(
|
||||||
: null,
|
padding: EdgeInsets.all(16),
|
||||||
|
child: Text(
|
||||||
|
product.notes,
|
||||||
|
style: TextStyle(fontSize: 16),
|
||||||
),
|
),
|
||||||
FieldGrid(fields),
|
),
|
||||||
Divider(
|
],
|
||||||
height: 1.0,
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.all(16),
|
|
||||||
child: Text(
|
|
||||||
product.notes,
|
|
||||||
style: TextStyle(fontSize: 16),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|
||||||
const _CustomAppBar({
|
|
||||||
@required this.viewModel,
|
|
||||||
});
|
|
||||||
|
|
||||||
final ProductViewVM viewModel;
|
|
||||||
|
|
||||||
@override
|
|
||||||
final Size preferredSize = const Size(double.infinity, kToolbarHeight);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final userCompany = viewModel.state.userCompany;
|
|
||||||
final product = viewModel.product;
|
|
||||||
|
|
||||||
return AppBar(
|
|
||||||
automaticallyImplyLeading: isMobile(context),
|
|
||||||
title: EntityStateTitle(entity: product),
|
|
||||||
actions: [
|
|
||||||
userCompany.canEditEntity(product)
|
|
||||||
? EditIconButton(
|
|
||||||
isVisible: !product.isDeleted,
|
|
||||||
onPressed: () => viewModel.onEditPressed(context),
|
|
||||||
)
|
|
||||||
: Container(),
|
|
||||||
ActionMenuButton(
|
|
||||||
entityActions: product.getActions(userCompany: userCompany),
|
|
||||||
isSaving: viewModel.isSaving,
|
|
||||||
entity: product,
|
|
||||||
onSelected: viewModel.onEntityAction,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,8 +5,6 @@ import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/product/product_actions.dart';
|
import 'package:invoiceninja_flutter/redux/product/product_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/product/product_screen.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/product/view/product_view.dart';
|
import 'package:invoiceninja_flutter/ui/product/view/product_view.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import 'package:invoiceninja_flutter/ui/app/buttons/edit_icon_button.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_state_title.dart';
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_state_title.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/icon_message.dart';
|
import 'package:invoiceninja_flutter/ui/app/icon_message.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/entity_header.dart';
|
import 'package:invoiceninja_flutter/ui/app/entity_header.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/view_scaffold.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/client/view/client_view_overview.dart';
|
import 'package:invoiceninja_flutter/ui/client/view/client_view_overview.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/project/view/project_view_vm.dart';
|
import 'package:invoiceninja_flutter/ui/project/view/project_view_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||||
|
|
@ -39,7 +40,7 @@ class _ProjectViewState extends State<ProjectView> {
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_timer = Timer.periodic(Duration(seconds: 1),
|
_timer = Timer.periodic(Duration(seconds: 1),
|
||||||
(Timer timer) => mounted ? setState(() => false) : false);
|
(Timer timer) => mounted ? setState(() => false) : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -78,134 +79,97 @@ class _ProjectViewState extends State<ProjectView> {
|
||||||
value: project.customValue2);
|
value: project.customValue2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return WillPopScope(
|
return ViewScaffold(
|
||||||
onWillPop: () async {
|
entity: project,
|
||||||
viewModel.onBackPressed();
|
body: Builder(
|
||||||
return true;
|
builder: (BuildContext context) {
|
||||||
},
|
List<Widget> _buildView() {
|
||||||
child: Scaffold(
|
final widgets = <Widget>[
|
||||||
appBar: _CustomAppBar(
|
EntityHeader(
|
||||||
viewModel: viewModel,
|
label: localization.total,
|
||||||
),
|
value: formatDuration(taskDurationForProject(
|
||||||
body: Builder(
|
project, viewModel.state.taskState.map)),
|
||||||
builder: (BuildContext context) {
|
secondLabel: localization.budgeted,
|
||||||
List<Widget> _buildView() {
|
secondValue: formatDuration(
|
||||||
final widgets = <Widget>[
|
Duration(hours: project.budgetedHours.toInt()),
|
||||||
EntityHeader(
|
showSeconds: false),
|
||||||
label: localization.total,
|
),
|
||||||
value: formatDuration(taskDurationForProject(
|
Material(
|
||||||
project, viewModel.state.taskState.map)),
|
color: Theme
|
||||||
secondLabel: localization.budgeted,
|
.of(context)
|
||||||
secondValue: formatDuration(
|
.canvasColor,
|
||||||
Duration(hours: project.budgetedHours.toInt()),
|
child: ListTile(
|
||||||
showSeconds: false),
|
title: EntityStateTitle(entity: client),
|
||||||
|
leading: Icon(FontAwesomeIcons.users, size: 18.0),
|
||||||
|
trailing: Icon(Icons.navigate_next),
|
||||||
|
onTap: () => viewModel.onClientPressed(context),
|
||||||
|
onLongPress: () => viewModel.onClientPressed(context, true),
|
||||||
),
|
),
|
||||||
Material(
|
),
|
||||||
color: Theme.of(context).canvasColor,
|
Container(
|
||||||
child: ListTile(
|
color: Theme
|
||||||
title: EntityStateTitle(entity: client),
|
.of(context)
|
||||||
leading: Icon(FontAwesomeIcons.users, size: 18.0),
|
.backgroundColor,
|
||||||
trailing: Icon(Icons.navigate_next),
|
height: 12.0,
|
||||||
onTap: () => viewModel.onClientPressed(context),
|
),
|
||||||
onLongPress: () => viewModel.onClientPressed(context, true),
|
EntityListTile(
|
||||||
),
|
icon: getEntityIcon(EntityType.task),
|
||||||
),
|
title: localization.tasks,
|
||||||
Container(
|
onTap: () => viewModel.onTasksPressed(context),
|
||||||
color: Theme.of(context).backgroundColor,
|
onLongPress: () =>
|
||||||
height: 12.0,
|
viewModel.onTasksPressed(context, longPress: true),
|
||||||
),
|
subtitle: memoizedTaskStatsForProject(
|
||||||
EntityListTile(
|
project.id, viewModel.state.taskState.map)
|
||||||
icon: getEntityIcon(EntityType.task),
|
.present(localization.active, localization.archived),
|
||||||
title: localization.tasks,
|
),
|
||||||
onTap: () => viewModel.onTasksPressed(context),
|
Container(
|
||||||
onLongPress: () =>
|
color: Theme
|
||||||
viewModel.onTasksPressed(context, longPress: true),
|
.of(context)
|
||||||
subtitle: memoizedTaskStatsForProject(
|
.backgroundColor,
|
||||||
project.id, viewModel.state.taskState.map)
|
height: 12.0,
|
||||||
.present(localization.active, localization.archived),
|
),
|
||||||
),
|
];
|
||||||
Container(
|
|
||||||
color: Theme.of(context).backgroundColor,
|
|
||||||
height: 12.0,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (project.privateNotes != null &&
|
|
||||||
project.privateNotes.isNotEmpty) {
|
|
||||||
widgets.addAll([
|
|
||||||
IconMessage(project.privateNotes),
|
|
||||||
Container(
|
|
||||||
color: Theme.of(context).backgroundColor,
|
|
||||||
height: 12.0,
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (project.privateNotes != null &&
|
||||||
|
project.privateNotes.isNotEmpty) {
|
||||||
widgets.addAll([
|
widgets.addAll([
|
||||||
FieldGrid(fields),
|
IconMessage(project.privateNotes),
|
||||||
|
Container(
|
||||||
|
color: Theme
|
||||||
|
.of(context)
|
||||||
|
.backgroundColor,
|
||||||
|
height: 12.0,
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return widgets;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return RefreshIndicator(
|
widgets.addAll([
|
||||||
onRefresh: () => viewModel.onRefreshed(context),
|
FieldGrid(fields),
|
||||||
child: ListView(
|
]);
|
||||||
children: _buildView(),
|
|
||||||
),
|
return widgets;
|
||||||
);
|
}
|
||||||
},
|
|
||||||
),
|
return RefreshIndicator(
|
||||||
floatingActionButton: FloatingActionButton(
|
onRefresh: () => viewModel.onRefreshed(context),
|
||||||
heroTag: 'project_view_fab',
|
child: ListView(
|
||||||
backgroundColor: Theme.of(context).primaryColorDark,
|
children: _buildView(),
|
||||||
onPressed: () => viewModel.onAddTaskPressed(context),
|
),
|
||||||
child: Icon(
|
);
|
||||||
Icons.add,
|
},
|
||||||
color: Colors.white,
|
),
|
||||||
),
|
floatingActionButton: FloatingActionButton(
|
||||||
tooltip: localization.newTask,
|
heroTag: 'project_view_fab',
|
||||||
|
backgroundColor: Theme
|
||||||
|
.of(context)
|
||||||
|
.primaryColorDark,
|
||||||
|
onPressed: () => viewModel.onAddTaskPressed(context),
|
||||||
|
child: Icon(
|
||||||
|
Icons.add,
|
||||||
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
|
tooltip: localization.newTask,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|
||||||
const _CustomAppBar({
|
|
||||||
@required this.viewModel,
|
|
||||||
});
|
|
||||||
|
|
||||||
final ProjectViewVM viewModel;
|
|
||||||
|
|
||||||
@override
|
|
||||||
final Size preferredSize = const Size(double.infinity, kToolbarHeight);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final project = viewModel.project;
|
|
||||||
final userCompany = viewModel.state.userCompany;
|
|
||||||
|
|
||||||
return AppBar(
|
|
||||||
automaticallyImplyLeading: isMobile(context),
|
|
||||||
title: EntityStateTitle(entity: project),
|
|
||||||
actions: project.isNew
|
|
||||||
? []
|
|
||||||
: [
|
|
||||||
userCompany.canEditEntity(project)
|
|
||||||
? EditIconButton(
|
|
||||||
isVisible: !project.isDeleted,
|
|
||||||
onPressed: () => viewModel.onEditPressed(context),
|
|
||||||
)
|
|
||||||
: Container(),
|
|
||||||
ActionMenuButton(
|
|
||||||
entityActions: project.getActions(
|
|
||||||
client: viewModel.client, userCompany: userCompany),
|
|
||||||
isSaving: viewModel.isSaving,
|
|
||||||
entity: project,
|
|
||||||
onSelected: viewModel.onEntityAction,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -6,9 +6,7 @@ import 'package:invoiceninja_flutter/data/models/project_model.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/project/project_actions.dart';
|
import 'package:invoiceninja_flutter/redux/project/project_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/project/project_screen.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/project/view/project_view.dart';
|
import 'package:invoiceninja_flutter/ui/project/view/project_view.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,11 @@ import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/document/document_actions.dart';
|
import 'package:invoiceninja_flutter/redux/document/document_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
|
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_vm.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/quote/quote_screen.dart';
|
|
||||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,9 @@ import 'package:invoiceninja_flutter/data/models/task_model.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/task/task_actions.dart';
|
import 'package:invoiceninja_flutter/redux/task/task_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/task/task_screen.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/task/view/task_view.dart';
|
import 'package:invoiceninja_flutter/ui/task/view/task_view.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:invoiceninja_flutter/constants.dart';
|
import 'package:invoiceninja_flutter/constants.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/tax_rate/tax_rate_screen.dart';
|
|
||||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,8 @@ import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/forms/app_form.dart';
|
import 'package:invoiceninja_flutter/ui/app/forms/app_form.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
|
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/user/edit/user_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/user/edit/user_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/buttons/action_flat_button.dart';
|
|
||||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
|
||||||
import 'package:invoiceninja_flutter/utils/strings.dart';
|
import 'package:invoiceninja_flutter/utils/strings.dart';
|
||||||
|
|
||||||
class UserEdit extends StatefulWidget {
|
class UserEdit extends StatefulWidget {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:invoiceninja_flutter/constants.dart';
|
import 'package:invoiceninja_flutter/constants.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/user/user_screen.dart';
|
|
||||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,7 @@ import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/vendor_model.dart';
|
import 'package:invoiceninja_flutter/data/models/vendor_model.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
|
||||||
import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart';
|
import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/vendor/vendor_screen.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/vendor/view/vendor_view.dart';
|
import 'package:invoiceninja_flutter/ui/vendor/view/vendor_view.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue