mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-29 05:56:47 +00:00
Stock display now uses infinite scroll
This commit is contained in:
parent
64e544c043
commit
d9a92216d2
@ -346,6 +346,8 @@ class _PaginatedPartListState extends State<PaginatedPartList> {
|
||||
|
||||
static const _pageSize = 25;
|
||||
|
||||
String _searchTerm;
|
||||
|
||||
final int categoryId;
|
||||
|
||||
_PaginatedPartListState(this.categoryId);
|
||||
@ -357,12 +359,28 @@ class _PaginatedPartListState extends State<PaginatedPartList> {
|
||||
_pagingController.addPageRequestListener((pageKey) {
|
||||
_fetchPage(pageKey);
|
||||
});
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_pagingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _fetchPage(int pageKey) async {
|
||||
try {
|
||||
|
||||
final page = await InvenTreePart().listPaginated(_pageSize, pageKey, filters: {"category": "${categoryId}"});
|
||||
Map<String, String> filters = {
|
||||
"category": "${categoryId}",
|
||||
};
|
||||
|
||||
if (_searchTerm != null && _searchTerm.isNotEmpty) {
|
||||
filters["search"] = _searchTerm;
|
||||
}
|
||||
|
||||
final page = await InvenTreePart().listPaginated(_pageSize, pageKey, filters: filters);
|
||||
final isLastPage = page.length < _pageSize;
|
||||
|
||||
// Construct a list of part objects
|
||||
@ -413,8 +431,34 @@ class _PaginatedPartListState extends State<PaginatedPartList> {
|
||||
);
|
||||
}
|
||||
|
||||
void updateSearchTerm(String searchTerm) {
|
||||
_searchTerm = searchTerm;
|
||||
_pagingController.refresh();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
// TODO: Introduce searching within the list
|
||||
/*
|
||||
SliverToBoxAdapter(child: TextField(
|
||||
onChanged: updateSearchTerm,
|
||||
)
|
||||
),
|
||||
*/
|
||||
PagedSliverList.separated(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<InvenTreePart>(
|
||||
itemBuilder: (context, item, index) {
|
||||
return _buildPart(context, item);
|
||||
}
|
||||
),
|
||||
separatorBuilder: (context, index) => const Divider(height: 1),
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
return PagedListView<int, InvenTreePart>.separated(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<InvenTreePart>(
|
||||
|
@ -16,6 +16,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||
|
||||
class LocationDisplayWidget extends StatefulWidget {
|
||||
|
||||
@ -159,18 +160,6 @@ class _LocationDisplayState extends RefreshableState<LocationDisplayWidget> {
|
||||
});
|
||||
|
||||
setState(() {});
|
||||
|
||||
await InvenTreeStockItem().list(context, filters: {"location": "$pk"}).then((var items) {
|
||||
_items.clear();
|
||||
|
||||
for (var item in items) {
|
||||
if (item is InvenTreeStockItem) {
|
||||
_items.add(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
Widget locationDescriptionCard() {
|
||||
@ -240,9 +229,7 @@ class _LocationDisplayState extends RefreshableState<LocationDisplayWidget> {
|
||||
children: detailTiles(),
|
||||
);
|
||||
case 1:
|
||||
return ListView(
|
||||
children: stockTiles(),
|
||||
);
|
||||
return PaginatedStockList(location?.pk ?? null);
|
||||
case 2:
|
||||
return ListView(
|
||||
children: ListTile.divideTiles(
|
||||
@ -300,6 +287,8 @@ List<Widget> detailTiles() {
|
||||
)
|
||||
];
|
||||
|
||||
/*
|
||||
|
||||
if (loading) {
|
||||
tiles.add(progressIndicator());
|
||||
} else if (_items.length > 0) {
|
||||
@ -310,6 +299,7 @@ List<Widget> detailTiles() {
|
||||
subtitle: Text("No stock items available in this location")
|
||||
));
|
||||
}
|
||||
*/
|
||||
|
||||
return tiles;
|
||||
}
|
||||
@ -403,10 +393,83 @@ class SublocationList extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class StockList extends StatelessWidget {
|
||||
final List<InvenTreeStockItem> _items;
|
||||
/**
|
||||
* Widget for displaying a list of stock items within a stock location.
|
||||
*
|
||||
* Users server-side pagination for snappy results
|
||||
*/
|
||||
|
||||
StockList(this._items);
|
||||
class PaginatedStockList extends StatefulWidget {
|
||||
|
||||
final int locationId;
|
||||
|
||||
PaginatedStockList(this.locationId);
|
||||
|
||||
@override
|
||||
_PaginatedStockListState createState() => _PaginatedStockListState(locationId);
|
||||
}
|
||||
|
||||
|
||||
class _PaginatedStockListState extends State<PaginatedStockList> {
|
||||
|
||||
static const _pageSize = 25;
|
||||
|
||||
String _searchTerm;
|
||||
|
||||
final int locationId;
|
||||
|
||||
_PaginatedStockListState(this.locationId);
|
||||
|
||||
final PagingController<int, InvenTreeStockItem> _pagingController = PagingController(firstPageKey: 0);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_pagingController.addPageRequestListener((pageKey) {
|
||||
_fetchPage(pageKey);
|
||||
});
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_pagingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _fetchPage(int pageKey) async {
|
||||
try {
|
||||
|
||||
Map<String, String> filters = {
|
||||
"location": "${locationId}"
|
||||
};
|
||||
|
||||
if (_searchTerm != null && _searchTerm.isNotEmpty) {
|
||||
filters["search"] = "${_searchTerm}";
|
||||
}
|
||||
|
||||
final page = await InvenTreeStockItem().listPaginated(_pageSize, pageKey, filters: filters);
|
||||
final isLastPage = page.length < _pageSize;
|
||||
|
||||
// Construct a list of stock item objects
|
||||
List<InvenTreeStockItem> items = [];
|
||||
|
||||
for (var result in page.results) {
|
||||
if (result is InvenTreeStockItem) {
|
||||
items.add(result);
|
||||
}
|
||||
}
|
||||
|
||||
if (isLastPage) {
|
||||
_pagingController.appendLastPage(items);
|
||||
} else {
|
||||
final int nextPageKey = pageKey + page.length;
|
||||
_pagingController.appendPage(items, nextPageKey);
|
||||
}
|
||||
} catch (error) {
|
||||
_pagingController.error = error;
|
||||
}
|
||||
}
|
||||
|
||||
void _openItem(BuildContext context, int pk) {
|
||||
InvenTreeStockItem().get(context, pk).then((var item) {
|
||||
@ -416,9 +479,7 @@ class StockList extends StatelessWidget {
|
||||
});
|
||||
}
|
||||
|
||||
Widget _build(BuildContext context, int index) {
|
||||
InvenTreeStockItem item = _items[index];
|
||||
|
||||
Widget _buildItem(BuildContext context, InvenTreeStockItem item) {
|
||||
return ListTile(
|
||||
title: Text("${item.partName}"),
|
||||
subtitle: Text("${item.partDescription}"),
|
||||
@ -438,10 +499,19 @@ class StockList extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build (BuildContext context) {
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics: ClampingScrollPhysics(),
|
||||
separatorBuilder: (_, __) => const Divider(height: 3),
|
||||
itemBuilder: _build, itemCount: _items.length);
|
||||
return CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
// TODO - Search input
|
||||
PagedSliverList.separated(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<InvenTreeStockItem>(
|
||||
itemBuilder: (context, item, index) {
|
||||
return _buildItem(context, item);
|
||||
}
|
||||
),
|
||||
separatorBuilder: (context, item) => const Divider(height: 1),
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user