From 61d6f64d200ea9e168f09e904bca12e4956c8192 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 10 Jun 2018 05:54:18 -0700 Subject: [PATCH] Clients --- lib/ui/client/client_list_vm.dart | 2 +- lib/ui/client/client_screen.dart | 5 +- lib/ui/client/edit/client_details.dart | 35 +++++++++ lib/ui/client/edit/client_edit.dart | 81 ++++++++++++++++++++ lib/ui/client/edit/client_edit_vm.dart | 40 ++++++++++ lib/ui/client/view/client_details.dart | 8 +- lib/ui/client/{ => view}/client_view.dart | 11 +-- lib/ui/client/{ => view}/client_view_vm.dart | 10 ++- lib/utils/localization.dart | 2 + 9 files changed, 179 insertions(+), 15 deletions(-) create mode 100644 lib/ui/client/edit/client_details.dart create mode 100644 lib/ui/client/edit/client_edit.dart create mode 100644 lib/ui/client/edit/client_edit_vm.dart rename lib/ui/client/{ => view}/client_view.dart (93%) rename lib/ui/client/{ => view}/client_view_vm.dart (89%) diff --git a/lib/ui/client/client_list_vm.dart b/lib/ui/client/client_list_vm.dart index f355701ab..a036e0d0c 100644 --- a/lib/ui/client/client_list_vm.dart +++ b/lib/ui/client/client_list_vm.dart @@ -13,7 +13,7 @@ import 'package:invoiceninja/data/models/models.dart'; import 'package:invoiceninja/ui/client/client_list.dart'; import 'package:invoiceninja/redux/app/app_state.dart'; import 'package:invoiceninja/redux/client/client_actions.dart'; -import 'package:invoiceninja/ui/client/client_view_vm.dart'; +import 'package:invoiceninja/ui/client/view/client_view_vm.dart'; class ClientListBuilder extends StatelessWidget { ClientListBuilder({Key key}) : super(key: key); diff --git a/lib/ui/client/client_screen.dart b/lib/ui/client/client_screen.dart index 21eb44fc7..ce6a09c4d 100644 --- a/lib/ui/client/client_screen.dart +++ b/lib/ui/client/client_screen.dart @@ -1,11 +1,12 @@ import 'package:invoiceninja/ui/app/app_search.dart'; import 'package:invoiceninja/ui/app/app_search_button.dart'; +import 'package:invoiceninja/ui/client/edit/client_edit_vm.dart'; import 'package:invoiceninja/utils/localization.dart'; import 'package:invoiceninja/redux/app/app_state.dart'; import 'package:flutter/material.dart'; import 'package:invoiceninja/data/models/models.dart'; import 'package:invoiceninja/ui/client/client_list_vm.dart'; -import 'package:invoiceninja/ui/client/client_view_vm.dart'; +import 'package:invoiceninja/ui/client/view/client_view_vm.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:invoiceninja/redux/client/client_actions.dart'; import 'package:invoiceninja/ui/app/app_drawer_vm.dart'; @@ -56,7 +57,7 @@ class ClientScreen extends StatelessWidget { store.dispatch(SelectClientAction(ClientEntity())); Navigator .of(context) - .push(MaterialPageRoute(builder: (_) => ClientViewBuilder())); + .push(MaterialPageRoute(builder: (_) => ClientEditBuilder())); }, child: Icon(Icons.add), tooltip: localization.newClient, diff --git a/lib/ui/client/edit/client_details.dart b/lib/ui/client/edit/client_details.dart new file mode 100644 index 000000000..02f5962d3 --- /dev/null +++ b/lib/ui/client/edit/client_details.dart @@ -0,0 +1,35 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:invoiceninja/data/models/models.dart'; +import 'package:invoiceninja/utils/formatting.dart'; +import 'package:invoiceninja/utils/localization.dart'; +import 'package:invoiceninja/utils/platforms.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class ClientEditDetails extends StatefulWidget { + ClientEditDetails({this.client}); + + final ClientEntity client; + + @override + _ClientEditDetailsState createState() => new _ClientEditDetailsState(); +} + +class _ClientEditDetailsState extends State { + + @override + Widget build(BuildContext context) { + var localization = AppLocalization.of(context); + var client = widget.client; + + return Padding( + padding: EdgeInsets.all(12.0), + child: ListView( + + ), + ); + } +} + diff --git a/lib/ui/client/edit/client_edit.dart b/lib/ui/client/edit/client_edit.dart new file mode 100644 index 000000000..3bb33a523 --- /dev/null +++ b/lib/ui/client/edit/client_edit.dart @@ -0,0 +1,81 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:invoiceninja/ui/app/actions_menu_button.dart'; +import 'package:invoiceninja/ui/client/edit/client_details.dart'; +import 'package:invoiceninja/ui/client/edit/client_edit_vm.dart'; +import 'package:invoiceninja/ui/client/view/client_details.dart'; +import 'package:invoiceninja/ui/client/view/client_overview.dart'; +import 'package:invoiceninja/utils/localization.dart'; + +class ClientEdit extends StatefulWidget { + final ClientEditVM viewModel; + + ClientEdit({ + Key key, + @required this.viewModel, + }) : super(key: key); + + @override + _ClientEditState createState() => new _ClientEditState(); +} + +class _ClientEditState extends State + with SingleTickerProviderStateMixin { + + TabController _controller; + + @override + void initState() { + super.initState(); + _controller = new TabController(vsync: this, length: 1); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var localization = AppLocalization.of(context); + + return Scaffold( + appBar: AppBar( + title: Text(widget.viewModel.client.id == null + ? localization.newClient + : widget.viewModel.client + .displayName), // Text(localizations.clientDetails), + bottom: TabBar( + controller: _controller, + isScrollable: true, + tabs: [ + Tab( + text: localization.details, + ), + ], + ), + actions: widget.viewModel.client.id == null + ? [] + : [ + IconButton( + icon: Icon(Icons.edit), + onPressed: () { + // + }, + ), + ActionMenuButton( + entity: widget.viewModel.client, + ) + ], + ), + body: TabBarView( + controller: _controller, + children: [ + ClientEditDetails(client: widget.viewModel.client), + ], + ), + ); + } +} + diff --git a/lib/ui/client/edit/client_edit_vm.dart b/lib/ui/client/edit/client_edit_vm.dart new file mode 100644 index 000000000..1e8419178 --- /dev/null +++ b/lib/ui/client/edit/client_edit_vm.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_redux/flutter_redux.dart'; +import 'package:invoiceninja/data/models/models.dart'; +import 'package:invoiceninja/redux/app/app_state.dart'; +import 'package:invoiceninja/ui/client/edit/client_edit.dart'; +import 'package:redux/redux.dart'; + +class ClientEditBuilder extends StatelessWidget { + ClientEditBuilder({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return StoreConnector( + converter: (Store store) { + return ClientEditVM.fromStore(store); + }, + builder: (context, vm) { + return ClientEdit( + viewModel: vm, + ); + }, + ); + } +} + +class ClientEditVM { + final ClientEntity client; + + ClientEditVM({ + @required this.client, + }); + + factory ClientEditVM.fromStore(Store store) { + final client = store.state.clientState().editing; + + return ClientEditVM( + client: client, + ); + } +} diff --git a/lib/ui/client/view/client_details.dart b/lib/ui/client/view/client_details.dart index 207f60a81..3f15bf97a 100644 --- a/lib/ui/client/view/client_details.dart +++ b/lib/ui/client/view/client_details.dart @@ -8,16 +8,16 @@ import 'package:invoiceninja/utils/localization.dart'; import 'package:invoiceninja/utils/platforms.dart'; import 'package:url_launcher/url_launcher.dart'; -class ClientDetails extends StatefulWidget { - ClientDetails({this.client}); +class ClientViewDetails extends StatefulWidget { + ClientViewDetails({this.client}); final ClientEntity client; @override - _ClientDetailsState createState() => new _ClientDetailsState(); + _ClientViewDetailsState createState() => new _ClientViewDetailsState(); } -class _ClientDetailsState extends State { +class _ClientViewDetailsState extends State { Future _launched; Future _launchURL(BuildContext context, String url) async { diff --git a/lib/ui/client/client_view.dart b/lib/ui/client/view/client_view.dart similarity index 93% rename from lib/ui/client/client_view.dart rename to lib/ui/client/view/client_view.dart index 5a9fcc05d..3dbe5d067 100644 --- a/lib/ui/client/client_view.dart +++ b/lib/ui/client/view/client_view.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:invoiceninja/ui/app/actions_menu_button.dart'; -import 'package:invoiceninja/ui/client/client_view_vm.dart'; +import 'package:invoiceninja/ui/client/view/client_view_vm.dart'; import 'package:invoiceninja/ui/client/view/client_details.dart'; import 'package:invoiceninja/ui/client/view/client_overview.dart'; import 'package:invoiceninja/utils/localization.dart'; @@ -41,10 +41,7 @@ class _ClientViewState extends State return Scaffold( appBar: AppBar( - title: Text(widget.viewModel.client.id == null - ? localization.newClient - : widget.viewModel.client - .displayName), // Text(localizations.clientDetails), + title: Text(widget.viewModel.client.displayName), // Text(localizations.clientDetails), bottom: TabBar( controller: _controller, //isScrollable: true, @@ -63,7 +60,7 @@ class _ClientViewState extends State IconButton( icon: Icon(Icons.edit), onPressed: () { - // + widget.viewModel.onEditClicked(context); }, ), ActionMenuButton( @@ -76,7 +73,7 @@ class _ClientViewState extends State controller: _controller, children: [ ClientOverview(client: widget.viewModel.client), - ClientDetails(client: widget.viewModel.client), + ClientViewDetails(client: widget.viewModel.client), ], ), floatingActionButton: FloatingActionButton( diff --git a/lib/ui/client/client_view_vm.dart b/lib/ui/client/view/client_view_vm.dart similarity index 89% rename from lib/ui/client/client_view_vm.dart rename to lib/ui/client/view/client_view_vm.dart index 066988b4d..cd0fc0c2f 100644 --- a/lib/ui/client/client_view_vm.dart +++ b/lib/ui/client/view/client_view_vm.dart @@ -2,11 +2,12 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; +import 'package:invoiceninja/ui/client/edit/client_edit_vm.dart'; import 'package:invoiceninja/utils/localization.dart'; import 'package:redux/redux.dart'; import 'package:invoiceninja/redux/client/client_actions.dart'; import 'package:invoiceninja/data/models/models.dart'; -import 'package:invoiceninja/ui/client/client_view.dart'; +import 'package:invoiceninja/ui/client/view/client_view.dart'; import 'package:invoiceninja/redux/app/app_state.dart'; import 'package:invoiceninja/ui/app/snackbar_row.dart'; @@ -34,6 +35,7 @@ class ClientViewVM { final Function onDelete; final Function(BuildContext, ClientEntity) onSaveClicked; final Function(BuildContext, EntityAction) onActionSelected; + final Function(BuildContext) onEditClicked; final bool isLoading; final bool isDirty; @@ -42,6 +44,7 @@ class ClientViewVM { @required this.onDelete, @required this.onSaveClicked, @required this.onActionSelected, + @required this.onEditClicked, @required this.isLoading, @required this.isDirty, }); @@ -54,6 +57,11 @@ class ClientViewVM { isDirty: client.id == null, client: client, onDelete: () => false, + onEditClicked: (BuildContext context) { + Navigator + .of(context) + .push(MaterialPageRoute(builder: (_) => ClientEditBuilder())); + }, onSaveClicked: (BuildContext context, ClientEntity client) { final Completer completer = new Completer(); store.dispatch(SaveClientRequest(completer, client)); diff --git a/lib/utils/localization.dart b/lib/utils/localization.dart index 149ac9735..76367031c 100644 --- a/lib/utils/localization.dart +++ b/lib/utils/localization.dart @@ -58,6 +58,8 @@ class AppLocalization { 'copied_to_clipboard': 'Copied to clipboard', 'error': 'Error', 'could_not_launch': 'Could not aunch', + 'contacts': 'Contacts', + 'additional': 'Additional', 'product': 'Product', 'products': 'Products',