feat: Add inventory management feature with CRUD operations
- Implemented inventory screen to display items with details. - Added create, edit, and consume inventory screens for managing items. - Introduced consumption history screen to track item usage. - Created inventory repository and providers for API interactions. - Enhanced routing to include inventory-related paths. - Added necessary models for inventory items and consumption history. - Integrated error handling and loading states for better user experience.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../../core/api/api_providers.dart';
|
||||
import '../../../core/api/guarded_api_call.dart';
|
||||
import '../../auth/data/auth_providers.dart';
|
||||
import '../domain/inventory_item.dart';
|
||||
import '../domain/inventory_consumption.dart';
|
||||
import 'inventory_repository.dart';
|
||||
|
||||
final inventoryRepositoryProvider = Provider<InventoryRepository>((ref) {
|
||||
return InventoryRepository(ref.watch(apiClientProvider));
|
||||
});
|
||||
|
||||
final inventoryProvider = FutureProvider<List<InventoryItem>>((ref) async {
|
||||
final token = await ref.watch(authStateProvider.future);
|
||||
return guardedApiCall(
|
||||
ref,
|
||||
() => ref.read(inventoryRepositoryProvider).fetchInventory(token: token),
|
||||
);
|
||||
});
|
||||
|
||||
final inventoryDetailProvider =
|
||||
FutureProvider.family<InventoryItem, int>((ref, id) async {
|
||||
final token = await ref.watch(authStateProvider.future);
|
||||
return guardedApiCall(
|
||||
ref,
|
||||
() => ref.read(inventoryRepositoryProvider).fetchInventoryItem(id, token: token),
|
||||
);
|
||||
});
|
||||
|
||||
final consumptionHistoryProvider =
|
||||
FutureProvider.family<List<InventoryConsumption>, int>((ref, id) async {
|
||||
final token = await ref.watch(authStateProvider.future);
|
||||
return guardedApiCall(
|
||||
ref,
|
||||
() => ref
|
||||
.read(inventoryRepositoryProvider)
|
||||
.fetchConsumptionHistory(id, token: token),
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,76 @@
|
||||
import '../../../core/api/api_client.dart';
|
||||
import '../domain/inventory_item.dart';
|
||||
import '../domain/inventory_consumption.dart';
|
||||
|
||||
class InventoryRepository {
|
||||
final ApiClient _api;
|
||||
|
||||
const InventoryRepository(this._api);
|
||||
|
||||
Future<List<InventoryItem>> fetchInventory({
|
||||
String? location,
|
||||
String? sort,
|
||||
String? token,
|
||||
}) async {
|
||||
final params = <String, String>{};
|
||||
if (location != null && location.isNotEmpty) params['location'] = location;
|
||||
if (sort != null && sort.isNotEmpty) params['sort'] = sort;
|
||||
|
||||
final query = params.isEmpty
|
||||
? ''
|
||||
: '?${params.entries.map((e) => '${e.key}=${Uri.encodeComponent(e.value)}').join('&')}';
|
||||
|
||||
final data = await _api.getJson('/inventory$query', token: token);
|
||||
final list = data as List<dynamic>;
|
||||
return list.map((e) => InventoryItem.fromJson(e as Map<String, dynamic>)).toList();
|
||||
}
|
||||
|
||||
Future<InventoryItem> fetchInventoryItem(int id, {String? token}) async {
|
||||
final data = await _api.getJson('/inventory/$id', token: token);
|
||||
return InventoryItem.fromJson(data as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Future<InventoryItem> createInventoryItem(
|
||||
Map<String, dynamic> body, {
|
||||
String? token,
|
||||
}) async {
|
||||
final data = await _api.postJson('/inventory', body: body, token: token);
|
||||
return InventoryItem.fromJson(data as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Future<InventoryItem> updateInventoryItem(
|
||||
int id,
|
||||
Map<String, dynamic> body, {
|
||||
String? token,
|
||||
}) async {
|
||||
final data = await _api.patchJson('/inventory/$id', body: body, token: token);
|
||||
return InventoryItem.fromJson(data as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Future<void> deleteInventoryItem(int id, {String? token}) async {
|
||||
await _api.deleteJson('/inventory/$id', token: token);
|
||||
}
|
||||
|
||||
Future<InventoryItem> consumeInventoryItem(
|
||||
int id, {
|
||||
required double amountUsed,
|
||||
String? comment,
|
||||
String? token,
|
||||
}) async {
|
||||
final body = <String, dynamic>{'amountUsed': amountUsed};
|
||||
if (comment != null && comment.isNotEmpty) body['comment'] = comment;
|
||||
final data = await _api.postJson('/inventory/$id/consume', body: body, token: token);
|
||||
return InventoryItem.fromJson(data as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Future<List<InventoryConsumption>> fetchConsumptionHistory(
|
||||
int id, {
|
||||
String? token,
|
||||
}) async {
|
||||
final data = await _api.getJson('/inventory/$id/consumption-history', token: token);
|
||||
final list = data as List<dynamic>;
|
||||
return list
|
||||
.map((e) => InventoryConsumption.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user