first
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
/// [ChangeNotifier] that loads, filters, and mutates the in-memory item list.
|
||||
library;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../models/item.dart';
|
||||
import '../services/item_repository.dart';
|
||||
import '../services/storage_service.dart';
|
||||
|
||||
/// App-wide catalog state. Screens call [loadItems], [addItem], and [search].
|
||||
class ItemController extends ChangeNotifier {
|
||||
ItemController({
|
||||
required this._repository,
|
||||
required this._storage,
|
||||
}) {
|
||||
_repository.useRemoteData = _storage.useRemoteData;
|
||||
}
|
||||
|
||||
final ItemRepository _repository;
|
||||
final StorageService _storage;
|
||||
|
||||
List<Item> _items = const [];
|
||||
bool _isLoading = false;
|
||||
String? _error;
|
||||
|
||||
List<Item> get items => List.unmodifiable(_items);
|
||||
bool get isLoading => _isLoading;
|
||||
String? get error => _error;
|
||||
bool get useRemoteData => _repository.useRemoteData;
|
||||
int get count => _items.length;
|
||||
|
||||
Future<void> loadItems() async {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
// Small delay so the loading indicator is visible with local data.
|
||||
await Future<void>.delayed(const Duration(milliseconds: 250));
|
||||
_items = await _repository.fetchItems();
|
||||
} catch (error, stackTrace) {
|
||||
_error = 'Could not load items.';
|
||||
debugPrint('ItemController.loadItems failed: $error\n$stackTrace');
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setUseRemoteData(bool value) async {
|
||||
if (value == _repository.useRemoteData) return;
|
||||
_repository.useRemoteData = value;
|
||||
await _storage.setUseRemoteData(value);
|
||||
notifyListeners();
|
||||
await loadItems();
|
||||
}
|
||||
|
||||
/// Case-insensitive match against title, subtitle, and category.
|
||||
List<Item> search(String query) {
|
||||
final needle = query.trim().toLowerCase();
|
||||
if (needle.isEmpty) return items;
|
||||
|
||||
return _items.where((item) {
|
||||
return item.title.toLowerCase().contains(needle) ||
|
||||
item.subtitle.toLowerCase().contains(needle) ||
|
||||
item.category.label.toLowerCase().contains(needle);
|
||||
}).toList(growable: false);
|
||||
}
|
||||
|
||||
Item addItem({
|
||||
required String title,
|
||||
required String subtitle,
|
||||
required String description,
|
||||
required ItemCategory category,
|
||||
}) {
|
||||
final created = _repository.createLocal(
|
||||
title: title,
|
||||
subtitle: subtitle,
|
||||
description: description,
|
||||
category: category,
|
||||
);
|
||||
_items = [created, ..._items];
|
||||
notifyListeners();
|
||||
return created;
|
||||
}
|
||||
|
||||
Item? findById(String id) {
|
||||
for (final item in _items) {
|
||||
if (item.id == id) return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user