contragent view

null-safety-migration
suvaissov 2021-07-19 15:45:59 +06:00
parent 91e43dbcf4
commit fb9e4c5fec
18 changed files with 299 additions and 105 deletions

View File

@ -19,7 +19,7 @@ class Category {
int? id;
int? parentId;
String? name;
String name = '';
int? appCompanyId;
String? updatedAt;

View File

@ -6,7 +6,7 @@
class CategoryResponse {
int? id;
int? parentId;
String? name;
String name = '';
String? updatedAt;
static CategoryResponse? fromMap(dynamic map) {
@ -14,15 +14,15 @@ class CategoryResponse {
final CategoryResponse categoryResponseBean = CategoryResponse();
categoryResponseBean.id = map['id'] as int;
categoryResponseBean.parentId = map['parent_id'] as int;
categoryResponseBean.name = map['name'] as String;
categoryResponseBean.name = map['name'] as String;
categoryResponseBean.updatedAt = map['updated_at'] as String;
return categoryResponseBean;
}
Map toJson() => {
"id": id,
"parent_id": parentId,
"name": name,
"updated_at": updatedAt,
'id': id,
'parent_id': parentId,
'name': name,
'updated_at': updatedAt,
};
}

View File

@ -29,7 +29,7 @@ final Logger log = getLogger('SetSellStateAction');
final DbService _dbService = locator<DbService>();
ThunkAction<AppState> counterOrEditSellItem(
{required int transactionId, required num counter, num? price}) {
{required int transactionId, required double counter, double? price}) {
return (Store<AppState> store) async {
log.i('counterSellItem');
int? appCompanyId = store.state.userState!.auth!.companyId;
@ -62,7 +62,8 @@ ThunkAction<AppState> counterOrEditSellItem(
item.price = price;
item.count = counter;
} else {
item.count = (item.count ?? 0) + counter;
final String val = ((item.count ?? 0) + counter).toStringAsFixed(5);
item.count = num.parse(val);
}
transaction.data = jsonEncode(item.toMap());
_dbService.update(transactionTableName, transaction.toMap());

View File

@ -32,7 +32,7 @@ ThunkAction<AppState> authenticate(String email, String password) {
if ( result.operation!) {
_api.token = result.token!;
store.dispatch(SetUserStateAction(UserState(isLoading: false, auth: result)));
_navigation.replace(MainViewRoute);
_navigation.replace(mainViewRoute);
_afterAuth(store);
} else {
_dialogService.showDialog(title: 'Внимание', buttonTitle: 'Ok', description: result.message!);
@ -53,7 +53,7 @@ ThunkAction<AppState> authenticateByToken(String token) {
if ( result.operation!) {
_api.token = result.token!;
store.dispatch(SetUserStateAction(UserState(isLoading: false, auth: result)));
_navigation.replace(MainViewRoute);
_navigation.replace(mainViewRoute);
_afterAuth(store);
} else {
_dialogService.showDialog(title: 'Внимание', buttonTitle: 'Ok', description: result.message!);
@ -72,19 +72,19 @@ Future<void> auth(Store<AppState> store) async {
UserState? state = store.state.userState;
if(state != null) {
if (state.auth?.operation == false) {
_navigation.replace(LoginViewRoute);
_navigation.replace(loginViewRoute);
} else {
AuthResponse response = await _api.auth(state.auth?.token ?? '');
if (response.operation!) {
_api.token = response.token!;
_navigation.replace(MainViewRoute);
_navigation.replace(mainViewRoute);
_afterAuth(store);
} else {
_navigation.replace(LoginViewRoute);
_navigation.replace(loginViewRoute);
}
}
} else {
_navigation.replace(LoginViewRoute);
_navigation.replace(loginViewRoute);
}
} catch (e) {
print(e);
@ -100,7 +100,7 @@ Future<void> logout(Store<AppState> store) async {
if (result.operation!) {
_api.token = null;
store.dispatch(SetUserStateAction(UserState(isLoading: false, auth: AuthResponse())));
_navigation.replace(LoginViewRoute);
_navigation.replace(loginViewRoute);
} else {
_dialogService.showDialog(title: 'Внимание', buttonTitle: 'Ok', description: result.message!);
}

View File

@ -1,8 +1,10 @@
const String LoginViewRoute = "LoginView";
const String MainViewRoute = "MainView";
const String WorkViewRoute = "WorkView";
const String AddProductViewRoute = "AddProductView";
const String AddByBarcodeViewRoute = "AddByBarcodeView";
const String loginViewRoute = 'LoginView';
const String mainViewRoute = 'MainView';
const String workViewRoute = 'WorkView';
const String addProductViewRoute = 'AddProductView';
const String addByBarcodeViewRoute = 'AddByBarcodeView';
const String SettingPrinterBluetoothViewRoute = "SettingPrinterBluetoothView";
const String contragentSelectViewRoute = 'ContragentSelectViewRoute';
const String settingPrinterBluetoothViewRoute = 'SettingPrinterBluetoothView';
// Generate the views here

View File

@ -1,9 +1,10 @@
import 'package:satu/views/add_by_barcode/add_by_barcode_view.dart';
import 'package:satu/views/add_product/add_product_view.dart';
import 'package:satu/views/work/views/add_by_barcode/add_by_barcode_view.dart';
import 'package:satu/views/work/views/add_product/add_product_view.dart';
import 'package:satu/views/login/login_view.dart';
import 'package:satu/views/main/main_view.dart';
import 'package:satu/views/settings/printer_bluetooth/PrinterSelect.dart';
import 'package:satu/views/work/views/contragent/select_contragent_view.dart';
import 'package:satu/views/work/work_view.dart';
import './route_names.dart';
@ -11,37 +12,43 @@ import 'package:flutter/material.dart';
Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case LoginViewRoute:
case loginViewRoute:
//LoginModel model = settings.arguments as LoginModel;
return _getPageRoute(
routeName: settings.name!,
viewToShow: LoginView(),
);
case WorkViewRoute:
case workViewRoute:
return _getPageRoute(
routeName: settings.name!,
viewToShow: WorkView(),
);
case MainViewRoute:
case mainViewRoute:
return _getPageRoute(
routeName: settings.name!,
viewToShow: MainView(),
);
case AddProductViewRoute:
case addProductViewRoute:
return _getPageRoute(
routeName: settings.name!,
viewToShow: AddProductView(),
);
case AddByBarcodeViewRoute:
case addByBarcodeViewRoute:
return _getPageRoute(
routeName: settings.name!,
viewToShow: AddByBarcodeView(),
);
case SettingPrinterBluetoothViewRoute:
case settingPrinterBluetoothViewRoute:
return _getPageRoute(
routeName: settings.name!,
//viewToShow: PrinterSelectView(title: 'Принтер печати чеков',),
);
case contragentSelectViewRoute:
return _getPageRoute(
routeName: settings.name!,
viewToShow: SelectContragentView(),
);
// case ImageShowRoute:
// ImageShowModel data = settings.arguments as ImageShowModel;
// //return SlideRightRoute(widget: ImageShowContainer(data));

View File

@ -1,41 +0,0 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:satu/shared/app_colors.dart';
import 'package:satu/shared/shared_styles.dart';
import 'package:satu/shared/ui_helpers.dart';
class AddCategoryListItem extends StatelessWidget {
final String? name;
final Function? onPress;
const AddCategoryListItem({Key? key, this.name, this.onPress }) : super(key: key);
@override
Widget build(BuildContext context) {
return Card(
child: ListTile(
onTap: () => onPress!(),
contentPadding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
title: Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Container(
height: 50,
child: Center(
child: Text(
name!,
style: TextStyle(
fontWeight: FontWeight.w600, color: Colors.black, fontSize: 15),
overflow: TextOverflow.ellipsis,
maxLines: 3,
),
)
),
),
trailing: Icon(
Icons.arrow_right,
color: primaryColor,
),
),
);
}
}

View File

@ -105,8 +105,8 @@ class _LoginViewState extends State<LoginView> {
Future<void> scan() async {
final NavigatorService _nav = locator<NavigatorService>().push(AddByBarcodeViewRoute) as NavigatorService;
final dynamic result = await _nav.push(AddByBarcodeViewRoute) ;
final NavigatorService _nav = locator<NavigatorService>().push(addByBarcodeViewRoute) as NavigatorService;
final dynamic result = await _nav.push(addByBarcodeViewRoute) ;
if(result != null) {
if( result.length == 60 ) {
Redux.store?.dispatch(authenticateByToken(result as String));

View File

@ -21,7 +21,7 @@ class SettingsView extends StatelessWidget {
name: 'Принтер',
value: 'не выбран',
onTap: () {
_navigatorService.push(SettingPrinterBluetoothViewRoute);
_navigatorService.push(settingPrinterBluetoothViewRoute);
}
),
],

View File

@ -1,5 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:satu/core/services/navigator_service.dart';
import 'package:satu/core/utils/locator.dart';
import 'package:satu/routes/route_names.dart';
import 'package:satu/shared/app_colors.dart';
import 'package:satu/shared/shared_styles.dart';
import 'package:satu/widgets/dialog/modal_select_dialog.dart';
@ -16,7 +19,9 @@ class ContragentSelectBar extends StatelessWidget {
child: Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () {},
onTap: () {
locator<NavigatorService>().push(contragentSelectViewRoute);
},
child: Padding(
padding: EdgeInsets.symmetric( vertical: 8.w, horizontal: 15.w ),
child: Row(

View File

@ -10,11 +10,9 @@ import 'package:satu/core/services/dialog_service.dart';
import 'package:satu/core/services/navigator_service.dart';
import 'package:satu/core/utils/locator.dart';
import 'package:satu/core/utils/utils_parse.dart';
import 'package:satu/routes/route_names.dart';
import 'package:satu/shared/app_colors.dart';
import 'package:satu/shared/shared_styles.dart';
import 'package:satu/shared/ui_helpers.dart';
import 'package:satu/views/add_by_barcode/add_by_barcode_view.dart';
import 'package:satu/views/work/views/add_by_barcode/add_by_barcode_view.dart';
import 'package:satu/widgets/ui/product_title_widget.dart';
import 'dialog_edit_product.dart';
@ -234,8 +232,8 @@ class _ProductListItemState extends State<ProductListItem> {
isNumeric(response.responseCount)) {
Redux.store!.dispatch(counterOrEditSellItem(
transactionId: widget.transactionId!,
counter: num.parse(response.responseCount!),
price: num.parse(response.responsePrice!),
counter: double.parse(response.responseCount!),
price: double.parse(response.responsePrice!),
));
} else {
_dialogService.showDialog(description: 'Не верный формат');

View File

@ -44,7 +44,13 @@ class SellView extends StatelessWidget {
const ContragentSelectBar(
value: 'Частное лицо',
),
Visibility(visible: state.items!.isNotEmpty,child: const ProductsTitleBarBar(itemsExist: true, title: 'Товары',),),
Visibility(
visible: state.items!.isNotEmpty,
child: const ProductsTitleBarBar(
itemsExist: true,
title: 'Товары',
),
),
ListView.separated(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
@ -63,17 +69,22 @@ class SellView extends StatelessWidget {
);
},
separatorBuilder: (context, index) {
return const Divider(height: 1, color: disableColor,);
return const Divider(
height: 1,
color: disableColor,
);
},
),
],
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButtonLocation:
FloatingActionButtonLocation.centerDocked,
floatingActionButton: floatingActionButtonRender(),
);
});
}
/// render floating buttons
/// render floating buttons
Widget floatingActionButtonRender() {
return StoreConnector<AppState, SellState>(
converter: (Store<AppState> store) => store.state.sellState!,
@ -99,7 +110,8 @@ class SellView extends StatelessWidget {
FloatingActionButton(
elevation: 2,
mini: true,
onPressed: () => locator<NavigatorService>().push(AddProductViewRoute),
onPressed: () =>
locator<NavigatorService>().push(addProductViewRoute),
child: Icon(
Icons.add_rounded,
size: 40.sp,
@ -111,16 +123,24 @@ class SellView extends StatelessWidget {
elevation: 2,
mini: true,
onPressed: () async {
final NavigatorService _nav = locator<NavigatorService>().push(AddByBarcodeViewRoute) as NavigatorService;
final dynamic result = await _nav.push(AddByBarcodeViewRoute) ;
if(result !=null) {
final List<Good> goods = await locator<DictionaryService>().getGoodsByEan(result as String);
if(goods.isNotEmpty) {
Redux.store?.dispatch(addSellItem( good: goods.first));
final NavigatorService _nav =
locator<NavigatorService>()
.push(addByBarcodeViewRoute)
as NavigatorService;
final dynamic result =
await _nav.push(addByBarcodeViewRoute);
if (result != null) {
final List<Good> goods =
await locator<DictionaryService>()
.getGoodsByEan(result as String);
if (goods.isNotEmpty) {
Redux.store
?.dispatch(addSellItem(good: goods.first));
}
}
},
child: Icon(Icons.qr_code_rounded, size: 30.sp, color: whiteColor),
child: Icon(Icons.qr_code_rounded,
size: 30.sp, color: whiteColor),
),
],
)

View File

@ -8,7 +8,7 @@ import 'package:satu/core/services/navigator_service.dart';
import 'package:satu/core/utils/locator.dart';
import 'package:satu/shared/app_colors.dart';
import 'package:satu/shared/ui_helpers.dart';
import 'package:satu/views/add_product/component/add_category_list_item.dart';
import 'package:satu/views/work/views/add_product/component/add_category_list_item.dart';
import 'package:satu/widgets/bar/products_app_bar.dart';
import 'package:satu/widgets/bar/products_title_bar.dart';
import 'package:satu/widgets/fields/input_field.dart';

View File

@ -0,0 +1,45 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:satu/shared/app_colors.dart';
import 'package:satu/shared/shared_styles.dart';
import 'package:satu/shared/ui_helpers.dart';
class AddCategoryListItem extends StatelessWidget {
final String name;
final Function? onPress;
const AddCategoryListItem({Key? key, this.name = '', this.onPress})
: super(key: key);
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(color: whiteColor),
child: ListTile(
onTap: () => onPress!(),
contentPadding:
const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
title: Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Container(
height: 50,
child: Center(
child: Text(
name,
style: const TextStyle(
fontWeight: FontWeight.w600,
color: Colors.black,
fontSize: 15),
overflow: TextOverflow.ellipsis,
maxLines: 3,
),
)),
),
trailing: Icon(
Icons.arrow_right,
color: primaryColor,
),
),
);
}
}

View File

@ -2,11 +2,19 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:satu/shared/app_colors.dart';
import 'package:satu/shared/shared_styles.dart';
import 'package:satu/shared/ui_helpers.dart';
import 'package:satu/widgets/ui/product_title_widget.dart';
class AddProductListItem extends StatelessWidget {
const AddProductListItem(
{required this.name,
Key? key,
this.ean,
this.categoryName,
this.price,
this.count,
this.onPress})
: super(key: key);
final String name;
final String? ean;
final String? categoryName;
@ -15,8 +23,6 @@ class AddProductListItem extends StatelessWidget {
final Function? onPress;
const AddProductListItem({Key? key, required this.name, this.ean, this.categoryName, this.price, this.count, this.onPress}) : super(key: key);
@override
Widget build(BuildContext context) {
return Material(
@ -24,26 +30,31 @@ class AddProductListItem extends StatelessWidget {
child: InkWell(
onTap: () => onPress!(),
child: Container(
decoration: BoxDecoration(
color: whiteColor
),
decoration: const BoxDecoration(color: whiteColor),
child: Padding(
padding: const EdgeInsets.all(4.0),
padding: const EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
flex: 3,
child: ProductTitleWidget( name: name, ean: ean, categoryName: categoryName, ),
child: ProductTitleWidget(
name: name,
ean: ean,
categoryName: categoryName,
),
),
Flexible(
flex: 1,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('${price}', style: TextStyle( fontSize: ScreenUtil().setSp(18.0), fontWeight: FontWeight.bold ),),
Text(
'$price',
style: TextStyle(
fontSize: ScreenUtil().setSp(20.0),
fontWeight: FontWeight.bold),
),
],
),
),

View File

@ -0,0 +1,41 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:satu/shared/app_colors.dart';
import 'package:satu/shared/shared_styles.dart';
import 'package:satu/shared/ui_helpers.dart';
class ContragentListItem extends StatelessWidget {
const ContragentListItem({Key? key, this.name, this.onPress})
: super(key: key);
final String? name;
final Function? onPress;
@override
Widget build(BuildContext context) {
return ListTile(
onTap: () => onPress!(),
contentPadding:
const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
title: Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Container(
decoration: const BoxDecoration(color: whiteColor),
height: 50,
child: Center(
child: Text(
name!,
style: TextStyle(
fontWeight: FontWeight.w600,
color: Colors.black,
fontSize: 15),
overflow: TextOverflow.ellipsis,
maxLines: 3,
),
)),
),
);
}
}

View File

@ -0,0 +1,105 @@
import 'package:flutter/material.dart';
import 'package:satu/core/entity/category_entity.dart';
import 'package:satu/core/entity/goods_entity.dart';
import 'package:satu/core/redux/actions/sell_actions.dart';
import 'package:satu/core/redux/store.dart';
import 'package:satu/core/services/dictionary_service.dart';
import 'package:satu/core/services/navigator_service.dart';
import 'package:satu/core/utils/locator.dart';
import 'package:satu/shared/app_colors.dart';
import 'package:satu/shared/ui_helpers.dart';
import 'package:satu/views/work/views/add_product/component/add_category_list_item.dart';
import 'package:satu/widgets/bar/products_app_bar.dart';
import 'package:satu/widgets/bar/products_title_bar.dart';
import 'package:satu/widgets/fields/input_field.dart';
import 'companent/contragent_list_item.dart';
class SelectContragentView extends StatefulWidget {
@override
_SelectContragentViewState createState() => _SelectContragentViewState();
}
class _SelectContragentViewState extends State<SelectContragentView> {
final DictionaryService _dictionaryService = locator<DictionaryService>();
final NavigatorService _navigatorService = locator<NavigatorService>();
late TextEditingController _searchTextController;
final FocusNode _searchFocusNode = new FocusNode();
final List<Category> _contragents = [];
@override
void initState() {
_searchTextController = TextEditingController();
_searchTextController.addListener(() {
if (_searchTextController.text.isNotEmpty) {
searchByField(_searchTextController.text);
} else {
reset();
}
});
super.initState();
}
@override
void dispose() {
_searchTextController.dispose();
_searchFocusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const ProductsAppBar(
title: 'Контрагент',
),
body: Column(
children: [
InputField(
placeholder: 'Поиск по наименованию или коду товара',
search: true,
controller: _searchTextController,
fieldFocusNode: _searchFocusNode,
),
verticalSpaceTiny,
const ProductsTitleBarBar(
title: 'Выберите контрагента',
),
Expanded(
child: ListView.separated(
physics: const BouncingScrollPhysics(),
itemCount: _contragents.length,
itemBuilder: (BuildContext context, int index) {
final Category category = _contragents[index];
return ContragentListItem(
name: category.name,
key: Key('category_${category.id}'),
onPress: () => () {},
);
},
separatorBuilder: (BuildContext context, int index) {
return const Divider(
height: 1.0,
color: disableColor,
);
},
),
),
],
),
);
}
void reset() {
_searchTextController.clear();
}
void searchByField(String query) async {
List<Good> goods = await _dictionaryService.getGoodsByNameOrEan(query);
setState(() {
goods;
});
}
}