169 lines
5.6 KiB
Dart
169 lines
5.6 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/svg.dart';
|
|
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
|
import 'package:satu/core/models/dictionary/good/good_response_entity.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/routes/route_names.dart';
|
|
import 'package:satu/shared/app_colors.dart';
|
|
import 'package:satu/views/dictionaries/component/dictionary_list_tile.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 'package:satu/widgets/ui/product_title_widget.dart';
|
|
|
|
class GoodsDictionaryView extends StatefulWidget {
|
|
@override
|
|
_GoodsDictionaryViewState createState() => _GoodsDictionaryViewState();
|
|
}
|
|
|
|
class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
|
|
final DictionaryService _dictionaryService = locator<DictionaryService>();
|
|
final NavigatorService _navigatorService = locator<NavigatorService>();
|
|
late TextEditingController _searchTextController;
|
|
final FocusNode _searchFocusNode = FocusNode();
|
|
static const _pageSize = 20;
|
|
String query = '';
|
|
Timer? _debounce;
|
|
|
|
final PagingController<int, GoodResponseEntity> _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: ProductsAppBar(
|
|
title: 'Товары',
|
|
drawerShow: true,
|
|
actions: [
|
|
ClipRRect(
|
|
borderRadius: BorderRadius.circular(90),
|
|
child: Material(
|
|
color: Colors.transparent,
|
|
child: InkWell(
|
|
onTap: () {},
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: SvgPicture.asset(
|
|
'assets/images/svg/options.svg',
|
|
height: 20,
|
|
width: 20,
|
|
color: textColor,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
body: Column(
|
|
children: [
|
|
InputField(
|
|
placeholder: 'Поиск по наименованию товара или штрих-код',
|
|
search: true,
|
|
controller: _searchTextController,
|
|
fieldFocusNode: _searchFocusNode,
|
|
),
|
|
const ProductsTitleBarBar(title: 'Список товаров'),
|
|
Expanded(
|
|
child: PagedListView<int, GoodResponseEntity>.separated(
|
|
physics: const BouncingScrollPhysics(),
|
|
separatorBuilder: (BuildContext context, int index) {
|
|
return const Divider(
|
|
height: 1.0,
|
|
color: disableColor,
|
|
);
|
|
},
|
|
pagingController: _pagingController,
|
|
builderDelegate: PagedChildBuilderDelegate<GoodResponseEntity>(
|
|
itemBuilder:
|
|
(BuildContext context, GoodResponseEntity good, int index) {
|
|
return DictionaryTile(
|
|
key: Key('good_${good.id}'),
|
|
onPress: () async {
|
|
final dynamic result = await _navigatorService
|
|
.push(goodsEditRoute, arguments: good);
|
|
if (result != null && true == (result as bool)) {
|
|
_pagingController.refresh();
|
|
}
|
|
},
|
|
child: ProductTitleWidget(
|
|
name: good.name,
|
|
categoryName: good.categoryName,
|
|
ean: good.ean13,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
floatingActionButton: FloatingActionButton(
|
|
elevation: 2,
|
|
onPressed: () async {
|
|
final dynamic result = await _navigatorService.push(goodsEditRoute,
|
|
arguments: GoodResponseEntity());
|
|
if (result != null && true == (result as bool)) {
|
|
_pagingController.refresh();
|
|
}
|
|
},
|
|
child: const Icon(
|
|
Icons.add_rounded,
|
|
size: 34.0,
|
|
color: whiteColor,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void reset() {
|
|
_searchTextController.clear();
|
|
}
|
|
|
|
Future<void> _fetchData(int pageKey, int perPage, String? query) async {
|
|
final List<GoodResponseEntity> newItems = await _dictionaryService.getGoods(
|
|
page: pageKey,
|
|
filter: {'col': 'name', 'action': 'like', 'val': query ?? ''},
|
|
perpage: perPage);
|
|
|
|
final isLastPage = newItems.length < _pageSize;
|
|
if (isLastPage) {
|
|
_pagingController.appendLastPage(newItems);
|
|
} else {
|
|
final nextPageKey = pageKey + 1;
|
|
_pagingController.appendPage(newItems, nextPageKey);
|
|
}
|
|
}
|
|
}
|