This commit is contained in:
2026-07-11 17:47:40 +02:00
commit 6587779a58
66 changed files with 7325 additions and 0 deletions
+140
View File
@@ -0,0 +1,140 @@
import 'package:flutter/foundation.dart';
import '../models/bar_tab.dart';
import '../models/product.dart';
import '../models/tab_item.dart';
import '../services/bar_tab_service.dart';
import '../services/product_service.dart';
class BarScreenViewModel extends ChangeNotifier {
final BarTabService barTabService;
BarScreenViewModel({
required this.barTabService,
});
List<BarTab> _tabs = [];
String? _selectedTabId;
bool _isLoading = false;
bool _hasLoaded = false;
String? _errorMessage;
List<BarTab> get tabs => _tabs;
String? get selectedTabId => _selectedTabId;
bool get isLoading => _isLoading;
bool get hasLoaded => _hasLoaded;
String? get errorMessage => _errorMessage;
BarTab? get selectedTab {
if (_selectedTabId == null) return null;
try {
return _tabs.firstWhere((tab) => tab.id == _selectedTabId);
} catch (_) {
return null;
}
}
Future<void> ensureLoaded() async {
if (_hasLoaded || _isLoading) return;
await load();
}
Future<void> load() async {
if (_isLoading) return;
_isLoading = true;
_errorMessage = null;
notifyListeners();
try {
_tabs = await barTabService.getOpenTabs();
if (_selectedTabId == null ||
!_tabs.any((tab) => tab.id == _selectedTabId)) {
_selectedTabId = _tabs.isEmpty ? null : _tabs.first.id;
}
} catch (_) {
_errorMessage = 'Could not load bar screen.';
} finally {
_hasLoaded = true;
_isLoading = false;
notifyListeners();
}
}
void selectTab(String tabId) {
_selectedTabId = tabId;
notifyListeners();
}
Future<void> createTab(String customerName) async {
final tab = await barTabService.createTab(
customerName: customerName,
);
_selectedTabId = tab.id;
await _reloadTabs();
}
Future<void> addProductToSelectedTab(Product product) async {
final tab = selectedTab;
if (tab == null) return;
await barTabService.addProductToTab(
tabId: tab.id,
product: product,
);
await _reloadTabs();
}
Future<void> changeItemQuantity(
TabItem item,
int quantity,
) async {
await barTabService.updateTabItemQuantity(
tabItemId: item.id,
quantity: quantity,
);
await _reloadTabs();
}
Future<void> closeSelectedTab() async {
final tab = selectedTab;
if (tab == null) return;
await barTabService.closeTab(tab.id);
_selectedTabId = null;
await _reloadTabs();
}
Future<void> closeTab(String tabId) async {
await barTabService.closeTab(tabId);
if (_selectedTabId == tabId) {
_selectedTabId = null;
}
await _reloadTabs();
}
Future<void> _reloadTabs() async {
_tabs = await barTabService.getOpenTabs();
if (_selectedTabId == null || !_tabs.any((tab) => tab.id == _selectedTabId)) {
_selectedTabId = _tabs.isEmpty ? null : _tabs.first.id;
}
notifyListeners();
}
}
+107
View File
@@ -0,0 +1,107 @@
import 'package:flutter/foundation.dart';
import '../models/product.dart';
import '../services/product_service.dart';
class ProductListViewModel extends ChangeNotifier {
final ProductService productService;
ProductListViewModel({
required this.productService,
});
static const List<String> _defaultCategories = [
'Bier',
'Wijn',
'Frisdrank',
'Cocktails',
'Snacks',
'Coffee',
'Thee',
'Other',
];
List<Product> _products = [];
bool _isLoading = false;
bool _hasLoaded = false;
String? _errorMessage;
List<Product> get products => _products;
bool get isLoading => _isLoading;
bool get hasLoaded => _hasLoaded;
String? get errorMessage => _errorMessage;
Future<void> ensureLoaded() async {
if (_hasLoaded || _isLoading) return;
await loadProducts();
}
Future<void> loadProducts() async {
if (_isLoading) return;
_isLoading = true;
_errorMessage = null;
notifyListeners();
try {
_products = await productService.getProducts();
} catch (_) {
_errorMessage = 'Could not load products.';
} finally {
_hasLoaded = true;
_isLoading = false;
notifyListeners();
}
}
Future<void> addProduct({
required String name,
required String category,
required int stockQuantity,
required int lowStockThreshold,
required int priceInCents,
required String? imagePath,
}) async {
await productService.createProduct(
name: name,
category: category,
stockQuantity: stockQuantity,
lowStockThreshold: lowStockThreshold,
priceInCents: priceInCents,
imagePath: imagePath,
);
await loadProducts();
}
Future<void> updateProduct(Product product) async {
await productService.updateProduct(product);
await loadProducts();
}
Future<void> deleteProduct(String id) async {
await productService.deleteProduct(id);
await loadProducts();
}
Future<Product?> getProductById(String id) {
return productService.getProductById(id);
}
List<String> get categories {
final categories = {
..._defaultCategories,
..._products
.map((p) => p.category.trim())
.where((c) => c.isNotEmpty),
}.toList();
categories.sort();
return categories;
}
}