Initial commit: Sage Kitchen Management App v1.0.0

 Features implemented:
- Smart inventory tracking with Hive database
- Barcode scanning with auto-populated product info
- Multiple API fallbacks (Open Food Facts, UPCItemDB)
- Smart expiration date predictions by category
- Discord webhook notifications (persisted)
- Custom sage leaf vector icon
- Material Design 3 UI with sage green theme
- Privacy Policy & Terms of Service
- Local-first, privacy-focused architecture

🎨 UI/UX:
- Home dashboard with inventory stats
- Add Item screen with barcode integration
- Inventory list with expiration indicators
- Settings with persistent preferences
- About section with legal docs

🔧 Technical:
- Flutter 3.35.5 with Riverpod state management
- Hive 2.2.3 for local database
- Mobile scanner for barcode detection
- Feature-first architecture

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-04 13:54:21 -04:00
commit 7be7b270e6
155 changed files with 13133 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/food_item.dart';
import '../repositories/inventory_repository.dart';
import '../repositories/inventory_repository_impl.dart';
/// Provider for the inventory repository
final inventoryRepositoryProvider = Provider<InventoryRepository>((ref) {
return InventoryRepositoryImpl();
});
/// Provider for the inventory controller
final inventoryControllerProvider =
StateNotifierProvider<InventoryController, AsyncValue<List<FoodItem>>>(
(ref) {
final repository = ref.watch(inventoryRepositoryProvider);
return InventoryController(repository);
},
);
/// Controller for managing inventory state
class InventoryController extends StateNotifier<AsyncValue<List<FoodItem>>> {
final InventoryRepository _repository;
InventoryController(this._repository) : super(const AsyncValue.loading()) {
loadItems();
}
/// Load all items from the database
Future<void> loadItems() async {
state = const AsyncValue.loading();
try {
final items = await _repository.getAllItems();
state = AsyncValue.data(items);
} catch (e, stack) {
state = AsyncValue.error(e, stack);
}
}
/// Add a new item
Future<void> addItem(FoodItem item) async {
await _repository.addItem(item);
await loadItems(); // Refresh the list
}
/// Update an existing item
Future<void> updateItem(FoodItem item) async {
await _repository.updateItem(item);
await loadItems();
}
/// Delete an item
Future<void> deleteItem(int id) async {
await _repository.deleteItem(id);
await loadItems();
}
/// Get items by location
Future<List<FoodItem>> getItemsByLocation(Location location) async {
return await _repository.getItemsByLocation(location);
}
/// Get items expiring soon
Future<List<FoodItem>> getItemsExpiringSoon(int days) async {
return await _repository.getItemsExpiringWithinDays(days);
}
}
/// Provider for items expiring within 7 days
final expiringSoonProvider = FutureProvider<List<FoodItem>>((ref) async {
final repository = ref.watch(inventoryRepositoryProvider);
return await repository.getItemsExpiringWithinDays(7);
});
/// Provider for total item count
final itemCountProvider = FutureProvider<int>((ref) async {
final repository = ref.watch(inventoryRepositoryProvider);
return await repository.getItemCount();
});