diff --git a/lib/inventree/model.dart b/lib/inventree/model.dart index a15f6a6f..c761f543 100644 --- a/lib/inventree/model.dart +++ b/lib/inventree/model.dart @@ -69,6 +69,24 @@ class InvenTreeModel { } */ + // Return the detail view for the associated pk + Future get(int pk) async { + + // TODO - Add "timeout" + // TODO - Add error catching + + var response = await InvenTreeAPI().get(path.join(URL, pk.toString())); + + if (response.statusCode != 200) { + print("Error retrieving data"); + return null; + } + + final data = json.decode(response.body); + + return createFromJson(data); + } + // Return list of objects from the database, with optional filters Future> list({Map filters}) async { diff --git a/lib/main.dart b/lib/main.dart index 5e2940ec..14813527 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:InvenTree/widget/category_display.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; // import 'package:preferences/preferences.dart'; @@ -166,6 +167,10 @@ class _MyHomePageState extends State { //Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeSettingsWidget())); } + void _showParts() { + Navigator.push(context, MaterialPageRoute(builder: (context) => CategoryDisplayWidget(-1))); + } + @override Widget build(BuildContext context) { // This method is rerun every time setState is called, for instance as done @@ -197,6 +202,17 @@ class _MyHomePageState extends State { title: new Text("InvenTree"), ), new Divider(), + new ListTile( + title: new Text("Scan"), + ), + new ListTile( + title: new Text("Parts"), + onTap: _showParts, + ), + new ListTile( + title: new Text("Stock"), + ), + new Divider(), new ListTile( title: new Text("Settings"), leading: new Icon(Icons.settings), diff --git a/lib/widget/category_display.dart b/lib/widget/category_display.dart new file mode 100644 index 00000000..75e806e0 --- /dev/null +++ b/lib/widget/category_display.dart @@ -0,0 +1,187 @@ + +import 'package:InvenTree/inventree/part.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +class CategoryDisplayWidget extends StatefulWidget { + + CategoryDisplayWidget(int catId, {this.category, Key key}) : categoryId = catId, super(key: key); + + InvenTreePartCategory category = null; + + final String title = "Category"; + + final int categoryId; + + @override + _CategoryDisplayState createState() => _CategoryDisplayState(categoryId, category: category); +} + + +class _CategoryDisplayState extends State { + + _CategoryDisplayState(int id, {this.category}) : categoryId = id { + _requestData(); + } + + final int categoryId; + + // The local InvenTreePartCategory object + InvenTreePartCategory category = null; + + List subcategories = List(); + + List parts = List(); + + String get _titleString { + + if (category == null) { + return "Part Categories"; + } else { + return "Part Category '${category.name}'"; + } + } + + /* + * Request data from the server + */ + void _requestData() { + + // Request a list of sub-categories under this one + InvenTreePartCategory().list(filters: {"parent": "$categoryId"}).then((var cats) { + subcategories.clear(); + + print("Returned categories: ${cats.length}"); + + for (var cat in cats) { + if (cat is InvenTreePartCategory) { + subcategories.add(cat); + } + } + + // Update state + setState(() {}); + }); + + // Request a list of parts under this category + InvenTreePart().list(filters: {"category": "$categoryId"}).then((var parts) { + parts.clear(); + + print("Returned parts: ${parts.length}"); + + for (var part in parts) { + if (part is InvenTreePart) { + parts.add(part); + print("Adding part: ${part.name}"); + } + } + + // Update state + setState(() {}); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(_titleString), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Subcategories", + ), + Expanded(child: SubcategoryList(subcategories)), + Divider(), + Text("Parts"), + Expanded(child: PartList(parts)), + Spacer(), + ] + ) + ) + ); + } +} + + +/* + * Builder for displaying a list of PartCategory objects + */ +class SubcategoryList extends StatelessWidget { + final List _categories; + + SubcategoryList(this._categories); + + void _openCategory(BuildContext context, int pk) { + + // Attempt to load the sub-category. + InvenTreePartCategory().get(pk).then((var cat) { + if (cat is InvenTreePartCategory) { + print("Found cat: <${cat.pk}> : ${cat.name} - ${cat.description}"); + + Navigator.push(context, MaterialPageRoute(builder: (context) => CategoryDisplayWidget(pk, category: cat))); + } + }); + } + + Widget _build(BuildContext context, int index) { + InvenTreePartCategory cat; + + if (index < _categories.length) { + cat = _categories[index]; + } + + return Card( + child: InkWell( + child: Column( + children: [ + Text('${cat.name} - ${cat.description}'), + ], + ), + onTap: () { + _openCategory(context, cat.pk); + } + ), + ); + } + + @override + Widget build(BuildContext context) { + return ListView.builder(itemBuilder: _build, itemCount: _categories.length); + } +} + + +/* + * Builder for displaying a list of Part objects + */ +class PartList extends StatelessWidget { + final List _parts; + + PartList(this._parts); + + Widget _build(BuildContext context, int index) { + InvenTreePart part; + + if (index < _parts.length) { + part = _parts[index]; + } + + return Card( + child: Column( + children: [ + Text('${part.name} - ${part.description}'), + ] + ) + ); + } + + @override + Widget build(BuildContext context) { + return ListView.builder(itemBuilder: _build, itemCount: _parts.length); + } +} diff --git a/lib/widget/drawer.dart b/lib/widget/drawer.dart new file mode 100644 index 00000000..e69de29b