Add glitchtip for centralized error logging

This commit is contained in:
2026-07-30 02:32:30 +02:00
parent 498ad68e1c
commit c210f80f27
15 changed files with 416 additions and 193 deletions
+81 -35
View File
@@ -1,4 +1,5 @@
import 'package:flutter/foundation.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import '../models/payment_method.dart';
import '../models/bar_tab.dart';
@@ -76,10 +77,16 @@ class BarScreenViewModel extends ChangeNotifier {
}
Future<void> createTab(String customerName) async {
final tab = await barTabService.createTab(customerName: customerName);
_selectedTabId = tab.id;
await _reloadTabs();
try {
final tab = await barTabService.createTab(customerName: customerName);
_selectedTabId = tab.id;
await _reloadTabs();
} catch (e, stack) {
debugPrint('BarScreenViewModel: createTab error: $e');
_errorMessage = 'Could not create tab.';
notifyListeners();
Sentry.captureException(e, stackTrace: stack);
}
}
Future<void> addProductToSelectedTab(Product product) async {
@@ -88,34 +95,52 @@ class BarScreenViewModel extends ChangeNotifier {
if (tab == null) return;
if (product.stockQuantity <= 0) {
throw Exception('Product is out of stock.');
_errorMessage = 'Product is out of stock.';
notifyListeners();
return;
}
await barTabService.addProductToTab(
tabId: tab.id,
product: product,
stockAdjustment: () => inventory.decreaseStock(product.id, 1),
);
try {
await barTabService.addProductToTab(
tabId: tab.id,
product: product,
stockAdjustment: () => inventory.decreaseStock(product.id, 1),
);
await _reloadTabs();
await _reloadTabs();
} catch (e, stack) {
debugPrint('BarScreenViewModel: addProductToSelectedTab error: $e');
_errorMessage = 'Could not add product to tab.';
notifyListeners();
Sentry.captureException(e, stackTrace: stack);
rethrow;
}
}
Future<void> changeItemQuantity(TabItem item, int quantity) async {
final difference = quantity - item.quantity;
await barTabService.updateTabItemQuantity(
tabItemId: item.id,
quantity: quantity,
stockAdjustment: () async {
if (difference > 0) {
await inventory.decreaseStock(item.productId, difference);
} else if (difference < 0) {
await inventory.increaseStock(item.productId, -difference);
}
},
);
try {
await barTabService.updateTabItemQuantity(
tabItemId: item.id,
quantity: quantity,
stockAdjustment: () async {
if (difference > 0) {
await inventory.decreaseStock(item.productId, difference);
} else if (difference < 0) {
await inventory.increaseStock(item.productId, -difference);
}
},
);
await _reloadTabs();
await _reloadTabs();
} catch (e, stack) {
debugPrint('BarScreenViewModel: changeItemQuantity error: $e');
_errorMessage = 'Could not update item quantity.';
notifyListeners();
Sentry.captureException(e, stackTrace: stack);
rethrow;
}
}
Future<void> closeSelectedTab({PaymentMethod paymentMethod = PaymentMethod.cash}) async {
@@ -123,25 +148,46 @@ class BarScreenViewModel extends ChangeNotifier {
if (tab == null) return;
await barTabService.closeTab(tab.id, paymentMethod: paymentMethod);
await _reloadTabs();
try {
await barTabService.closeTab(tab.id, paymentMethod: paymentMethod);
await _reloadTabs();
} catch (e, stack) {
debugPrint('BarScreenViewModel: closeSelectedTab error: $e');
_errorMessage = 'Could not close tab.';
notifyListeners();
Sentry.captureException(e, stackTrace: stack);
rethrow;
}
}
Future<void> closeTab(String tabId, {PaymentMethod paymentMethod = PaymentMethod.cash}) async {
await barTabService.closeTab(tabId, paymentMethod: paymentMethod);
await _reloadTabs();
try {
await barTabService.closeTab(tabId, paymentMethod: paymentMethod);
await _reloadTabs();
} catch (e, stack) {
debugPrint('BarScreenViewModel: closeTab error: $e');
_errorMessage = 'Could not close tab.';
notifyListeners();
Sentry.captureException(e, stackTrace: stack);
rethrow;
}
}
Future<void> _reloadTabs() async {
_tabs = await barTabService.getOpenTabs();
try {
_tabs = await barTabService.getOpenTabs();
if (_selectedTabId == null ||
!_tabs.any((tab) => tab.id == _selectedTabId)) {
_selectedTabId = _tabs.isEmpty ? null : _tabs.first.id;
if (_selectedTabId == null ||
!_tabs.any((tab) => tab.id == _selectedTabId)) {
_selectedTabId = _tabs.isEmpty ? null : _tabs.first.id;
}
notifyListeners();
} catch (e, stack) {
debugPrint('BarScreenViewModel: reloadTabs error: $e');
_errorMessage = 'Could not reload tabs.';
notifyListeners();
Sentry.captureException(e, stackTrace: stack);
}
notifyListeners();
}
}
+7
View File
@@ -6,6 +6,7 @@ import 'package:kooltab2/models/payment_method.dart';
import 'package:kooltab2/services/pin_lock_service.dart';
import 'package:kooltab2/services/product_service.dart';
import 'package:kooltab2/services/settings_service.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:uuid/uuid.dart';
class DevMenuViewModel extends ChangeNotifier {
@@ -255,6 +256,12 @@ class DevMenuViewModel extends ChangeNotifier {
_isLoading = false;
notifyListeners();
}
try {
throw Exception('Test GlitchTip error!');
} catch (exception, stackTrace) {
Sentry.captureException(exception, stackTrace: stackTrace);
}
}
Future<void> generateMockOrders({int count = 100}) async {
+37 -18
View File
@@ -1,4 +1,5 @@
import 'package:flutter/foundation.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import '../models/product.dart';
import '../services/product_service.dart';
@@ -13,35 +14,53 @@ class InventoryViewModel extends ChangeNotifier {
List<Product> get products => _products;
Future<void> load() async {
_products = await productService.getProducts();
notifyListeners();
try {
_products = await productService.getProducts();
notifyListeners();
} catch (e, stack) {
debugPrint('InventoryViewModel: load error: $e');
Sentry.captureException(e, stackTrace: stack);
rethrow;
}
}
Future<void> decreaseStock(String productId, int amount) async {
await productService.decreaseStock(productId, amount);
try {
await productService.decreaseStock(productId, amount);
final index = _products.indexWhere((product) => product.id == productId);
final index = _products.indexWhere((product) => product.id == productId);
if (index != -1) {
_products[index] = _products[index].copyWith(
stockQuantity: _products[index].stockQuantity - amount,
);
if (index != -1) {
_products[index] = _products[index].copyWith(
stockQuantity: _products[index].stockQuantity - amount,
);
}
notifyListeners();
} catch (e, stack) {
debugPrint('InventoryViewModel: decreaseStock error: $e');
Sentry.captureException(e, stackTrace: stack);
rethrow;
}
notifyListeners();
}
Future<void> increaseStock(String productId, int amount) async {
await productService.increaseStock(productId, amount);
try {
await productService.increaseStock(productId, amount);
final index = _products.indexWhere((product) => product.id == productId);
final index = _products.indexWhere((product) => product.id == productId);
if (index != -1) {
_products[index] = _products[index].copyWith(
stockQuantity: _products[index].stockQuantity + amount,
);
if (index != -1) {
_products[index] = _products[index].copyWith(
stockQuantity: _products[index].stockQuantity + amount,
);
}
notifyListeners();
} catch (e, stack) {
debugPrint('InventoryViewModel: increaseStock error: $e');
Sentry.captureException(e, stackTrace: stack);
rethrow;
}
notifyListeners();
}
}
+38 -13
View File
@@ -1,4 +1,5 @@
import 'package:flutter/foundation.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import '../models/product.dart';
import '../services/product_service.dart';
@@ -66,26 +67,50 @@ class ProductListViewModel extends ChangeNotifier {
required int priceInCents,
required String? imagePath,
}) async {
await productService.createProduct(
name: name,
category: category,
stockQuantity: stockQuantity,
lowStockThreshold: lowStockThreshold,
priceInCents: priceInCents,
imagePath: imagePath,
);
try {
await productService.createProduct(
name: name,
category: category,
stockQuantity: stockQuantity,
lowStockThreshold: lowStockThreshold,
priceInCents: priceInCents,
imagePath: imagePath,
);
await loadProducts();
await loadProducts();
} catch (e, stack) {
debugPrint('ProductListViewModel: addProduct error: $e');
_errorMessage = 'Could not add product.';
notifyListeners();
Sentry.captureException(e, stackTrace: stack);
rethrow;
}
}
Future<void> updateProduct(Product product) async {
await productService.updateProduct(product);
await loadProducts();
try {
await productService.updateProduct(product);
await loadProducts();
} catch (e, stack) {
debugPrint('ProductListViewModel: updateProduct error: $e');
_errorMessage = 'Could not update product.';
notifyListeners();
Sentry.captureException(e, stackTrace: stack);
rethrow;
}
}
Future<void> deleteProduct(String id) async {
await productService.deleteProduct(id);
await loadProducts();
try {
await productService.deleteProduct(id);
await loadProducts();
} catch (e, stack) {
debugPrint('ProductListViewModel: deleteProduct error: $e');
_errorMessage = 'Could not delete product.';
notifyListeners();
Sentry.captureException(e, stackTrace: stack);
rethrow;
}
}
Future<Product?> getProductById(String id) {