Files
flutter_wisetronic/lib/widgets/desktop/product_search.dart
2022-03-10 00:47:26 -05:00

181 lines
5.3 KiB
Dart

import 'package:dio/dio.dart';
import 'package:flappy_search_bar/flappy_search_bar.dart';
import 'package:flutter/material.dart';
import '../../constants.dart';
import '../../events/eventbus.dart';
import '../../events/events.dart';
import '../../generated/l10n.dart';
import '../../models/business.dart';
import '../../models/product.dart';
import '../../pages/product_detail_page.dart';
import '../../utils/http_util.dart';
import '../../utils/utils.dart';
import '../../widgets/general/bottom_nav.dart';
import '../../widgets/general/breadcrumbs.dart';
import '../../widgets/general/navigationbar.dart';
import 'product_item.dart';
class ProductSearch extends StatefulWidget {
final Business business;
const ProductSearch(this.business, {Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => ProductSearchState();
}
class ProductSearchState extends State<ProductSearch> {
double sideSpace = 0;
double mainSpace = 1200;
double rate = 1;
int page = 1;
int numPerPage = 10;
int lastResultSize = 0;
double lastBottomPosition = 0;
String lastKeyword = '';
SearchBarController _controller = SearchBarController<Product>();
@override
Widget build(BuildContext context) {
if (MediaQuery.of(context).size.width <= 1200) {
mainSpace = MediaQuery.of(context).size.width;
sideSpace = 0;
} else {
mainSpace = 1200;
sideSpace = (MediaQuery.of(context).size.width - 1200) / 2;
}
rate = mainSpace / 1200;
return Scaffold(
appBar: MiniNavigationBar(
title: S.of(context).search_product,
back: true,
breadCrumbs: [
BreadCrumb(S.of(context).search_product, null),
],
breadCrumbHeight: Constants.BREADCRUMB_HEIGHT,
),
drawer: null,
body: SafeArea(
child: Container(
child: Row(
children: [
Container(
width: sideSpace,
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: NotificationListener<ScrollNotification>(
child: SearchBar(
searchBarController: _controller,
minimumChars: 2,
hintText: S.of(context).enter_keyword,
cancellationWidget: Text(
S.of(context).cancel,
),
onSearch: search,
onItemFound: (Product searchProduct, int index) {
return ProductItem(
searchProduct,
widget.business,
horizontal: true,
);
},
onError: (error) {
return Center(
child: Text("$error"),
);
},
emptyWidget: Center(
child: Text(
S.of(context).empty_result_change_keyword,
),
),
),
onNotification: (notification) {
if (notification.metrics.atEdge) {
print('fff: $page, $lastBottomPosition, ${notification.metrics.pixels}');
if (page != 0 && lastResultSize >= numPerPage && notification.metrics.pixels != 0) {
if (notification.metrics.pixels > lastBottomPosition) {
lastBottomPosition = notification.metrics.pixels;
page += 1;
_controller.replayLastSearch();
}
}
}
return true;
},
),
),
),
Container(
width: sideSpace,
),
],
),
),
),
bottomNavigationBar: BottomNav(),
);
}
Future<List<Product>> search(String keyword) async {
if (lastKeyword != keyword) {
page = 1;
}
lastKeyword = keyword;
var result = await HttpUtil.httpGet('v1/search-store-product2',
queryParameters: {
'store_id': widget.business.id,
'keyword': keyword,
'page': page,
'num_per_page': numPerPage,
},
returnError: true,
);
if (result is DioError) {
if (result.response != null) {
throw RuntimeError(result.response.data);
} else {
throw RuntimeError(result.message);
}
} else if (result != null && result is List) {
lastBottomPosition = 0;
var r = result.map((e) => Product.fromJson(e)).toList();
lastResultSize = r.length;
if (lastResultSize < numPerPage) {
page = 1;
}
return r;
}
return [];
}
@override
void initState() {
super.initState();
eventBus.on<OnCartInfoUpdated>().listen((event) {
if (mounted) {
setState(() {});
}
});
}
void _showProductDetail(Product p) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductDetailPage(
product: p,
business: widget.business,
)),
);
}
}