@@ -28,8 +28,13 @@ class ServiceFilesBloc extends Bloc<ServiceFilesEvent, ServiceFilesState> {
|
||||
on<LoadServiceFilesEvent>(_onLoadServiceFiles);
|
||||
on<AddServiceFilesEvent>(_onAddServiceFiles);
|
||||
on<UploadServiceFilesEvent>(_onUploadServiceFiles);
|
||||
on<UploadMultipleServiceFilesEvent>(_onUploadMultipleServiceFiles);
|
||||
on<DeleteServiceFilesEvent>(_onDeleteServiceFiles);
|
||||
on<ToggleServiceFileSelectionEvent>(_onToggleServiceFileSelection);
|
||||
// Se il BLoC nasce con un ID, accendiamo subito lo stream!
|
||||
if (serviceId != null) {
|
||||
add(LoadServiceFilesEvent(serviceId: serviceId));
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _onServiceSaved(
|
||||
@@ -80,8 +85,9 @@ class ServiceFilesBloc extends Bloc<ServiceFilesEvent, ServiceFilesState> {
|
||||
AddServiceFilesEvent event,
|
||||
Emitter<ServiceFilesState> emit,
|
||||
) async {
|
||||
final currentId = state.serviceId;
|
||||
// BIVIO 1: PRATICA NUOVA (Nessun ID)
|
||||
if (serviceId == null) {
|
||||
if (currentId == null) {
|
||||
// Mettiamo i file nel "parcheggio" locale dello State
|
||||
final newLocalFiles = event.files.map((file) {
|
||||
return ServiceFileModel(
|
||||
@@ -139,7 +145,7 @@ class ServiceFilesBloc extends Bloc<ServiceFilesEvent, ServiceFilesState> {
|
||||
if (event.pickedFiles != null && event.pickedFiles!.isNotEmpty) {
|
||||
for (var file in event.pickedFiles!) {
|
||||
await _repository.uploadAndRegisterServiceFile(
|
||||
serviceId: serviceId!,
|
||||
serviceId: state.serviceId!,
|
||||
pickedFile: file,
|
||||
);
|
||||
}
|
||||
@@ -152,13 +158,75 @@ class ServiceFilesBloc extends Bloc<ServiceFilesEvent, ServiceFilesState> {
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _onUploadMultipleServiceFiles(
|
||||
UploadMultipleServiceFilesEvent event,
|
||||
Emitter<ServiceFilesState> emit,
|
||||
) async {
|
||||
if (event.files.isEmpty) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: ServiceFilesStatus.failure,
|
||||
error: "Nessun file selezionato",
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
emit(state.copyWith(status: ServiceFilesStatus.uploading, error: null));
|
||||
try {
|
||||
// 2. Creiamo una lista di "Promesse" (Futures) per il repository
|
||||
final List<Future<void>> uploadTasks = [];
|
||||
for (var file in event.files) {
|
||||
// Aggiungiamo il task alla lista, ma NON usiamo await qui dentro!
|
||||
uploadTasks.add(
|
||||
_repository.uploadAndRegisterServiceFile(
|
||||
serviceId: state.serviceId!,
|
||||
pickedFile: file,
|
||||
),
|
||||
);
|
||||
}
|
||||
// 3. ESECUZIONE PARALLELA!
|
||||
// Aspettiamo che tutti i file siano caricati contemporaneamente.
|
||||
await Future.wait(uploadTasks);
|
||||
// 4. GRAN FINALE: Tutto caricato, emettiamo il success!
|
||||
emit(state.copyWith(status: ServiceFilesStatus.success));
|
||||
} catch (e) {
|
||||
// Se anche un solo file fallisce, catturiamo l'errore
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: ServiceFilesStatus.failure,
|
||||
error: "Errore durante l'upload multiplo: $e",
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _onDeleteServiceFiles(
|
||||
DeleteServiceFilesEvent event,
|
||||
Emitter<ServiceFilesState> emit,
|
||||
) {}
|
||||
) async {
|
||||
emit(state.copyWith(status: ServiceFilesStatus.loading));
|
||||
try {
|
||||
await _repository.deleteServiceFiles(state.selectedFiles);
|
||||
emit(
|
||||
state.copyWith(status: ServiceFilesStatus.success, selectedFiles: []),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(status: ServiceFilesStatus.failure, error: e.toString()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _onToggleServiceFileSelection(
|
||||
ToggleServiceFileSelectionEvent event,
|
||||
Emitter<ServiceFilesState> emit,
|
||||
) {}
|
||||
) {
|
||||
List<ServiceFileModel> selectedFiles = List.from(state.selectedFiles);
|
||||
if (selectedFiles.contains(event.file)) {
|
||||
selectedFiles.remove(event.file);
|
||||
} else {
|
||||
selectedFiles.add(event.file);
|
||||
}
|
||||
emit(state.copyWith(selectedFiles: selectedFiles));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,13 @@ class UploadServiceFilesEvent extends ServiceFilesEvent {
|
||||
List<Object?> get props => [pickedFiles, photos];
|
||||
}
|
||||
|
||||
class UploadMultipleServiceFilesEvent extends ServiceFilesEvent {
|
||||
final List<PlatformFile> files;
|
||||
const UploadMultipleServiceFilesEvent(this.files);
|
||||
@override
|
||||
List<Object?> get props => [files];
|
||||
}
|
||||
|
||||
class DeleteServiceFilesEvent extends ServiceFilesEvent {}
|
||||
|
||||
class ToggleServiceFileSelectionEvent extends ServiceFilesEvent {
|
||||
|
||||
@@ -203,19 +203,31 @@ class ServicesCubit extends Cubit<ServicesState> {
|
||||
|
||||
// --- PERSISTENZA ---
|
||||
|
||||
Future<void> saveCurrentService({required bool isBozza}) async {
|
||||
Future<void> saveCurrentService({
|
||||
required bool isBozza,
|
||||
bool shouldPop = true,
|
||||
List<ServiceFileModel>? files,
|
||||
}) async {
|
||||
if (state.currentService == null) return;
|
||||
|
||||
emit(state.copyWith(status: ServicesStatus.saving, errorMessage: null));
|
||||
try {
|
||||
// 1. Aggiorniamo il flag bozza in base a quale pulsante ha premuto l'utente
|
||||
final serviceToSave = state.currentService!.copyWith(isBozza: isBozza);
|
||||
final serviceToSave = state.currentService!.copyWith(
|
||||
isBozza: isBozza,
|
||||
files: files,
|
||||
);
|
||||
|
||||
// 2. Salvataggio corazzato
|
||||
await _repository.saveFullService(serviceToSave);
|
||||
final updatedService = await _repository.saveFullService(serviceToSave);
|
||||
|
||||
// 3. Reset e ricaricamento
|
||||
emit(state.copyWith(status: ServicesStatus.saved, currentService: null));
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: shouldPop ? ServicesStatus.saved : ServicesStatus.savedNoPop,
|
||||
currentService: shouldPop ? null : updatedService,
|
||||
),
|
||||
);
|
||||
await loadServices(refresh: true);
|
||||
} catch (e) {
|
||||
emit(
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
part of 'services_cubit.dart';
|
||||
|
||||
enum ServicesStatus { initial, loading, ready, saving, saved, success, failure }
|
||||
enum ServicesStatus {
|
||||
initial,
|
||||
loading,
|
||||
ready,
|
||||
saving,
|
||||
saved,
|
||||
savedNoPop,
|
||||
success,
|
||||
failure,
|
||||
}
|
||||
|
||||
class ServicesState extends Equatable {
|
||||
final ServicesStatus status;
|
||||
@@ -10,6 +19,7 @@ class ServicesState extends Equatable {
|
||||
final String query;
|
||||
final DateTimeRange? dateRange;
|
||||
final bool hasReachedMax;
|
||||
final bool isSavingDraft;
|
||||
|
||||
const ServicesState({
|
||||
required this.status,
|
||||
@@ -19,6 +29,7 @@ class ServicesState extends Equatable {
|
||||
this.query = '',
|
||||
this.dateRange,
|
||||
this.hasReachedMax = false,
|
||||
this.isSavingDraft = false,
|
||||
});
|
||||
|
||||
ServicesState copyWith({
|
||||
@@ -29,6 +40,7 @@ class ServicesState extends Equatable {
|
||||
String? query,
|
||||
DateTimeRange? dateRange,
|
||||
bool? hasReachedMax,
|
||||
bool? isSavingDraft,
|
||||
}) {
|
||||
return ServicesState(
|
||||
status: status ?? this.status,
|
||||
@@ -38,6 +50,7 @@ class ServicesState extends Equatable {
|
||||
query: query ?? this.query,
|
||||
dateRange: dateRange ?? this.dateRange,
|
||||
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
|
||||
isSavingDraft: isSavingDraft ?? this.isSavingDraft,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -50,5 +63,6 @@ class ServicesState extends Equatable {
|
||||
query,
|
||||
dateRange,
|
||||
hasReachedMax,
|
||||
isSavingDraft,
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user