This commit is contained in:
2026-07-27 21:32:03 +02:00
parent 160b4e4cda
commit 77c1747b40
23 changed files with 1392 additions and 87 deletions
+21 -9
View File
@@ -8,9 +8,11 @@ import '../services/product_service.dart';
class BarScreenViewModel extends ChangeNotifier {
final BarTabService barTabService;
final ProductService productService;
BarScreenViewModel({
required this.barTabService,
required this.productService,
});
List<BarTab> _tabs = [];
@@ -74,9 +76,7 @@ class BarScreenViewModel extends ChangeNotifier {
}
Future<void> createTab(String customerName) async {
final tab = await barTabService.createTab(
customerName: customerName,
);
final tab = await barTabService.createTab(customerName: customerName);
_selectedTabId = tab.id;
await _reloadTabs();
@@ -87,23 +87,34 @@ class BarScreenViewModel extends ChangeNotifier {
if (tab == null) return;
if (product.stockQuantity <= 0) {
throw Exception('Product is out of stock.');
}
await barTabService.addProductToTab(
tabId: tab.id,
product: product,
);
await productService.decreaseStock(product.id, 1);
await _reloadTabs();
}
Future<void> changeItemQuantity(
TabItem item,
int quantity,
) async {
Future<void> changeItemQuantity(TabItem item, int quantity) async {
final difference = quantity - item.quantity;
await barTabService.updateTabItemQuantity(
tabItemId: item.id,
quantity: quantity,
);
if (difference > 0) {
await productService.decreaseStock(item.productId, difference);
} else if (difference < 0) {
await productService.increaseStock(item.productId, -difference);
}
await _reloadTabs();
}
@@ -126,10 +137,11 @@ class BarScreenViewModel extends ChangeNotifier {
Future<void> _reloadTabs() async {
_tabs = await barTabService.getOpenTabs();
if (_selectedTabId == null || !_tabs.any((tab) => tab.id == _selectedTabId)) {
if (_selectedTabId == null ||
!_tabs.any((tab) => tab.id == _selectedTabId)) {
_selectedTabId = _tabs.isEmpty ? null : _tabs.first.id;
}
notifyListeners();
}
}
}
@@ -56,6 +56,20 @@ class ProductListViewModel extends ChangeNotifier {
_isLoading = false;
notifyListeners();
}
try {
_products = await productService.getProducts();
debugPrint(
_products.map((p) => '${p.name}: ${p.stockQuantity}').join('\n'),
);
} catch (_) {
_errorMessage = 'Could not load products.';
} finally {
_hasLoaded = true;
_isLoading = false;
notifyListeners();
}
}
Future<void> addProduct({
+66
View File
@@ -0,0 +1,66 @@
import 'package:flutter/foundation.dart';
import '../models/settings.dart';
import '../services/settings_service.dart';
class SettingsViewModel extends ChangeNotifier {
final SettingsService settingsService;
SettingsViewModel({required this.settingsService});
AppSettings _settings = AppSettings.defaults;
bool _isLoading = false;
bool _hasLoaded = false;
String? _errorMessage;
AppSettings get settings => _settings;
bool get isLoading => _isLoading;
bool get hasLoaded => _hasLoaded;
String? get errorMessage => _errorMessage;
Future<void> ensureLoaded() async {
if (_hasLoaded || _isLoading) return;
await load();
}
Future<void> load() async {
if (_isLoading) return;
_isLoading = true;
_errorMessage = null;
notifyListeners();
try {
_settings = await settingsService.getSettings();
} catch (_) {
_errorMessage = 'Could not load settings.';
} finally {
_hasLoaded = true;
_isLoading = false;
notifyListeners();
}
}
/// Just flips the preference flag. Caller is responsible for having
/// already set/verified the actual PIN via PinLockViewModel first.
Future<void> updatePinRequired(bool value) =>
_save(_settings.copyWith(pinRequired: value));
Future<void> updateThemeMode(AppThemeMode mode) =>
_save(_settings.copyWith(themeMode: mode));
Future<void> _save(AppSettings updated) async {
final previous = _settings;
_settings = updated;
_errorMessage = null;
notifyListeners();
try {
await settingsService.saveSettings(updated);
} catch (_) {
_settings = previous;
_errorMessage = 'Could not save settings.';
notifyListeners();
}
}
}