180 lines
5.6 KiB
Dart
180 lines
5.6 KiB
Dart
import 'dart:async';
|
||
|
||
import 'package:flutter/material.dart';
|
||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||
import 'package:satu/core/models/inventarization/response/inventarization_response.dart';
|
||
import 'package:satu/core/models/stock/stock_response.dart';
|
||
import 'package:satu/core/services/dialog_service.dart';
|
||
import 'package:satu/core/services/stocks_service.dart';
|
||
import 'package:satu/views/inventarization/widget/good_inventarization_list_item.dart';
|
||
import 'package:satu/views/stocks/widget/stock_tile.dart';
|
||
|
||
import '../../../core/entity/goods_entity.dart';
|
||
import '../../../core/models/inventarization/good_item/good_item.dart';
|
||
import '../../../core/services/dictionary_service.dart';
|
||
import '../../../core/services/inventarization_service.dart';
|
||
import '../../../core/services/navigator_service.dart';
|
||
import '../../../core/utils/locator.dart';
|
||
import '../../../routes/route_names.dart';
|
||
import '../../../shared/app_colors.dart';
|
||
import '../../../shared/shared_styles.dart';
|
||
import '../../../shared/ui_helpers.dart';
|
||
import '../../../widgets/bar/products_app_bar.dart';
|
||
import '../../widgets/fields/input_field.dart';
|
||
|
||
class StocksView extends StatefulWidget {
|
||
const StocksView({
|
||
Key? key,
|
||
}) : super(key: key);
|
||
|
||
@override
|
||
State<StocksView> createState() => _StocksViewState();
|
||
}
|
||
|
||
class _StocksViewState extends State<StocksView> {
|
||
final StockService _service = locator<StockService>();
|
||
late TextEditingController _searchTextController;
|
||
final FocusNode _searchFocusNode = FocusNode();
|
||
String query = '';
|
||
Timer? _debounce;
|
||
|
||
static const _pageSize = 20;
|
||
bool _isLastPage = false;
|
||
|
||
final PagingController<int, StockResponse> _pagingController =
|
||
PagingController(firstPageKey: 1);
|
||
|
||
@override
|
||
void initState() {
|
||
_searchTextController = TextEditingController();
|
||
_searchTextController.addListener(() {
|
||
setState(() {
|
||
query = _searchTextController.text;
|
||
});
|
||
if (_debounce?.isActive ?? false) _debounce?.cancel();
|
||
_debounce = Timer(const Duration(milliseconds: 500), () {
|
||
_pagingController.refresh();
|
||
});
|
||
});
|
||
|
||
_pagingController.addPageRequestListener((pageKey) {
|
||
_fetchData(pageKey, _pageSize, query);
|
||
});
|
||
super.initState();
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
;
|
||
_debounce?.cancel();
|
||
_pagingController.dispose();
|
||
_searchTextController.dispose();
|
||
_searchFocusNode.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
appBar: const ProductsAppBar(
|
||
title: 'Остатки',
|
||
drawerShow: true,
|
||
),
|
||
body: Column(
|
||
children: [
|
||
InputField(
|
||
placeholder: 'Поиск по наименованию товара или штрих-код',
|
||
search: true,
|
||
controller: _searchTextController,
|
||
fieldFocusNode: _searchFocusNode,
|
||
),
|
||
verticalSpaceSmall,
|
||
Padding(
|
||
padding: const EdgeInsets.symmetric(horizontal: 15.0),
|
||
child: SizedBox(
|
||
width: double.infinity,
|
||
child: Row(
|
||
children: [
|
||
Expanded(
|
||
flex: 4,
|
||
child: Text(
|
||
'Список товара',
|
||
style: textGray11Style,
|
||
),
|
||
),
|
||
Expanded(
|
||
flex: 2,
|
||
child: Text(
|
||
'Количество',
|
||
style: textGray11Style,
|
||
),
|
||
),
|
||
Expanded(
|
||
flex: 1,
|
||
child: Text(
|
||
'Сумма',
|
||
style: textGray11Style,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
verticalSpaceSmall,
|
||
Expanded(
|
||
child: PagedListView<int, StockResponse>.separated(
|
||
//physics: const BouncingScrollPhysics(),
|
||
separatorBuilder: (BuildContext context, int index) {
|
||
return const Divider(
|
||
height: 1.0,
|
||
color: disableColor,
|
||
);
|
||
},
|
||
pagingController: _pagingController,
|
||
builderDelegate: PagedChildBuilderDelegate<StockResponse>(
|
||
noItemsFoundIndicatorBuilder: (BuildContext context) {
|
||
return const Center(
|
||
child: Text(
|
||
'В данном списке нет товаров',
|
||
style: textGray11Style,
|
||
),
|
||
);
|
||
},
|
||
itemBuilder:
|
||
(BuildContext context, StockResponse item, int index) {
|
||
return StockTile(
|
||
key: Key(
|
||
'good_stock_${item.eaccGoodId}',
|
||
),
|
||
name: item.name,
|
||
categoryName: item.katName,
|
||
count: item.cnt,
|
||
price: item.price,
|
||
ean: item.ean13,
|
||
);
|
||
},
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Future<void> _fetchData(int pageKey, int perPage, String? query) async {
|
||
final List<StockResponse> newItems = await _service.getList(
|
||
page: pageKey,
|
||
perpage: perPage,
|
||
query: query,
|
||
);
|
||
_isLastPage = newItems.length < _pageSize;
|
||
|
||
if (_isLastPage) {
|
||
_pagingController.appendLastPage(newItems);
|
||
} else {
|
||
final nextPageKey = pageKey + 1;
|
||
_pagingController.appendPage(newItems, nextPageKey);
|
||
}
|
||
}
|
||
}
|