Files
kooltab/lib/viewmodels/history_view_model.dart

157 lines
3.9 KiB
Dart

import 'package:flutter/foundation.dart';
import '../models/bar_tab.dart';
import '../models/closed_tab.dart';
import '../services/bar_tab_service.dart';
class HistoryViewModel extends ChangeNotifier {
final BarTabService barTabService;
HistoryViewModel({required this.barTabService});
static const int _pageSize = 20;
List<ClosedTab> _closedTabs = [];
List<BarTab> _openTabs = [];
List<String> _customerNames = [];
String? _selectedCustomer;
int _offset = 0;
int _totalCount = 0;
bool _isLoading = false;
bool _hasLoaded = false;
bool _isLoadingMore = false;
String? _errorMessage;
String _searchQuery = '';
List<ClosedTab> get closedTabs {
return _closedTabs
.where((tab) => _matchesCustomer(tab.customerName))
.toList();
}
List<BarTab> get openTabs {
return _openTabs
.where((tab) => _matchesCustomer(tab.customerName))
.toList();
}
List<String> get customerNames => _customerNames;
String? get selectedCustomer => _selectedCustomer;
bool get isLoading => _isLoading;
bool get hasLoaded => _hasLoaded;
bool get isLoadingMore => _isLoadingMore;
bool get hasMore => _closedTabs.length < _totalCount;
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 {
final results = await Future.wait([
_fetchPage(offset: 0),
barTabService.getClosedTabCount(customerName: _selectedCustomer),
barTabService.getDistinctCustomerNames(),
barTabService.getOpenTabs(includeRemoved: true),
]);
_closedTabs = (results[0] as List<ClosedTab>).toList()
..sort(_compareClosedTabs);
_totalCount = results[1] as int;
_openTabs = (results[3] as List<BarTab>).toList()..sort(_compareOpenTabs);
_customerNames = {
...(results[2] as List<String>),
..._openTabs.map((tab) => tab.customerName),
}.toList()..sort();
_offset = _closedTabs.length;
} catch (e) {
debugPrint('HistoryViewModel: load error: $e');
_errorMessage = 'Could not load tab history.';
} finally {
_hasLoaded = true;
_isLoading = false;
notifyListeners();
}
}
Future<void> loadMore() async {
if (_isLoadingMore || !hasMore) return;
_isLoadingMore = true;
notifyListeners();
try {
final more = await _fetchPage(offset: _offset);
_closedTabs = [..._closedTabs, ...more]..sort(_compareClosedTabs);
_offset = _closedTabs.length;
} catch (e) {
debugPrint('HistoryViewModel: loadMore error: $e');
_errorMessage = 'Could not load more tabs.';
} finally {
_isLoadingMore = false;
notifyListeners();
}
}
Future<List<ClosedTab>> _fetchPage({required int offset}) {
return barTabService.getClosedTabsPaginated(
limit: _pageSize,
offset: offset,
customerName: _selectedCustomer,
);
}
int _compareClosedTabs(ClosedTab a, ClosedTab b) {
final byClosedAt = b.closedAt.compareTo(a.closedAt);
if (byClosedAt != 0) return byClosedAt;
return b.id.compareTo(a.id);
}
int _compareOpenTabs(BarTab a, BarTab b) {
final byOpenedAt = b.openedAt.compareTo(a.openedAt);
if (byOpenedAt != 0) return byOpenedAt;
return b.id.compareTo(a.id);
}
void search(String query) {
_searchQuery = query;
notifyListeners();
}
bool _matchesCustomer(String customerName) {
if (_selectedCustomer != null && customerName != _selectedCustomer) {
return false;
}
if (_searchQuery.isEmpty) return true;
return customerName.toLowerCase().contains(_searchQuery.toLowerCase());
}
Future<void> filterByCustomer(String? customerName) async {
_selectedCustomer = customerName;
_searchQuery = '';
_offset = 0;
_closedTabs = [];
await load();
}
}