163 lines
4.5 KiB
Dart
163 lines
4.5 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import '../../data/models/scan_item.dart';
|
|
import '../../domain/usecases/get_scan_history_usecase.dart';
|
|
import 'dependency_injection.dart';
|
|
|
|
/// State for the scanner functionality
|
|
class ScannerState {
|
|
final String? currentBarcode;
|
|
final List<ScanItem> history;
|
|
final bool isLoading;
|
|
final String? error;
|
|
|
|
const ScannerState({
|
|
this.currentBarcode,
|
|
this.history = const [],
|
|
this.isLoading = false,
|
|
this.error,
|
|
});
|
|
|
|
ScannerState copyWith({
|
|
String? currentBarcode,
|
|
List<ScanItem>? history,
|
|
bool? isLoading,
|
|
String? error,
|
|
}) {
|
|
return ScannerState(
|
|
currentBarcode: currentBarcode ?? this.currentBarcode,
|
|
history: history ?? this.history,
|
|
isLoading: isLoading ?? this.isLoading,
|
|
error: error ?? this.error,
|
|
);
|
|
}
|
|
|
|
@override
|
|
bool operator ==(Object other) =>
|
|
identical(this, other) ||
|
|
other is ScannerState &&
|
|
runtimeType == other.runtimeType &&
|
|
currentBarcode == other.currentBarcode &&
|
|
history == other.history &&
|
|
isLoading == other.isLoading &&
|
|
error == other.error;
|
|
|
|
@override
|
|
int get hashCode =>
|
|
currentBarcode.hashCode ^
|
|
history.hashCode ^
|
|
isLoading.hashCode ^
|
|
error.hashCode;
|
|
}
|
|
|
|
/// Scanner state notifier
|
|
class ScannerNotifier extends StateNotifier<ScannerState> {
|
|
final GetScanHistoryUseCase _getScanHistoryUseCase;
|
|
|
|
ScannerNotifier(this._getScanHistoryUseCase) : super(const ScannerState()) {
|
|
_loadHistory();
|
|
}
|
|
|
|
/// Load scan history from local storage
|
|
Future<void> _loadHistory() async {
|
|
state = state.copyWith(isLoading: true, error: null);
|
|
|
|
final result = await _getScanHistoryUseCase();
|
|
result.fold(
|
|
(failure) => state = state.copyWith(
|
|
isLoading: false,
|
|
error: failure.message,
|
|
),
|
|
(history) => state = state.copyWith(
|
|
isLoading: false,
|
|
history: history.map((entity) => ScanItem.fromEntity(entity)).toList(),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Update current scanned barcode
|
|
void updateBarcode(String barcode) {
|
|
if (barcode.trim().isEmpty) return;
|
|
|
|
state = state.copyWith(currentBarcode: barcode);
|
|
|
|
// Add to history if not already present
|
|
final existingIndex = state.history.indexWhere((item) => item.barcode == barcode);
|
|
if (existingIndex == -1) {
|
|
final newScanItem = ScanItem(
|
|
barcode: barcode,
|
|
timestamp: DateTime.now(),
|
|
);
|
|
|
|
final updatedHistory = [newScanItem, ...state.history];
|
|
state = state.copyWith(history: updatedHistory);
|
|
} else {
|
|
// Move existing item to top
|
|
final existingItem = state.history[existingIndex];
|
|
final updatedHistory = List<ScanItem>.from(state.history);
|
|
updatedHistory.removeAt(existingIndex);
|
|
updatedHistory.insert(0, existingItem.copyWith(timestamp: DateTime.now()));
|
|
state = state.copyWith(history: updatedHistory);
|
|
}
|
|
}
|
|
|
|
/// Clear current barcode
|
|
void clearBarcode() {
|
|
state = state.copyWith(currentBarcode: null);
|
|
}
|
|
|
|
/// Refresh history from storage
|
|
Future<void> refreshHistory() async {
|
|
await _loadHistory();
|
|
}
|
|
|
|
/// Add or update scan item in history
|
|
void updateScanItem(ScanItem scanItem) {
|
|
final existingIndex = state.history.indexWhere(
|
|
(item) => item.barcode == scanItem.barcode,
|
|
);
|
|
|
|
List<ScanItem> updatedHistory;
|
|
if (existingIndex != -1) {
|
|
// Update existing item
|
|
updatedHistory = List<ScanItem>.from(state.history);
|
|
updatedHistory[existingIndex] = scanItem;
|
|
} else {
|
|
// Add new item at the beginning
|
|
updatedHistory = [scanItem, ...state.history];
|
|
}
|
|
|
|
state = state.copyWith(history: updatedHistory);
|
|
}
|
|
|
|
/// Clear error message
|
|
void clearError() {
|
|
state = state.copyWith(error: null);
|
|
}
|
|
}
|
|
|
|
/// Provider for scanner state
|
|
final scannerProvider = StateNotifierProvider<ScannerNotifier, ScannerState>(
|
|
(ref) => ScannerNotifier(
|
|
ref.watch(getScanHistoryUseCaseProvider),
|
|
),
|
|
);
|
|
|
|
/// Provider for current barcode (for easy access)
|
|
final currentBarcodeProvider = Provider<String?>((ref) {
|
|
return ref.watch(scannerProvider).currentBarcode;
|
|
});
|
|
|
|
/// Provider for scan history (for easy access)
|
|
final scanHistoryProvider = Provider<List<ScanItem>>((ref) {
|
|
return ref.watch(scannerProvider).history;
|
|
});
|
|
|
|
/// Provider for scanner loading state
|
|
final scannerLoadingProvider = Provider<bool>((ref) {
|
|
return ref.watch(scannerProvider).isLoading;
|
|
});
|
|
|
|
/// Provider for scanner error state
|
|
final scannerErrorProvider = Provider<String?>((ref) {
|
|
return ref.watch(scannerProvider).error;
|
|
}); |