feat-add-files-from-qr #8
@@ -17,7 +17,7 @@ class CustomerFilesBloc extends Bloc<CustomerFilesEvent, CustomerFilesState> {
|
|||||||
: super(const CustomerFilesState(status: CustomerFilesStatus.initial)) {
|
: super(const CustomerFilesState(status: CustomerFilesStatus.initial)) {
|
||||||
on<LoadCustomerFilesEvent>(_loadCustomerFiles);
|
on<LoadCustomerFilesEvent>(_loadCustomerFiles);
|
||||||
on<UploadCustomerFileEvent>(_uploadCustomerFile);
|
on<UploadCustomerFileEvent>(_uploadCustomerFile);
|
||||||
on<DeleteCustomerFileEvent>(_deleteCustomerFile);
|
on<DeleteCustomerFileEvent>(_deleteCustomerFiles);
|
||||||
on<ToggleCustomerFileSelectionEvent>(_toggleCustomerFileSelection);
|
on<ToggleCustomerFileSelectionEvent>(_toggleCustomerFileSelection);
|
||||||
}
|
}
|
||||||
void _loadCustomerFiles(
|
void _loadCustomerFiles(
|
||||||
@@ -60,14 +60,16 @@ class CustomerFilesBloc extends Bloc<CustomerFilesEvent, CustomerFilesState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _deleteCustomerFile(
|
Future<void> _deleteCustomerFiles(
|
||||||
DeleteCustomerFileEvent event,
|
DeleteCustomerFileEvent event,
|
||||||
Emitter<CustomerFilesState> emit,
|
Emitter<CustomerFilesState> emit,
|
||||||
) async {
|
) async {
|
||||||
emit(state.copyWith(status: CustomerFilesStatus.loading));
|
emit(state.copyWith(status: CustomerFilesStatus.loading));
|
||||||
try {
|
try {
|
||||||
await _repository.deleteDocument(event.file);
|
await _repository.deleteDocuments(state.selectedFiles);
|
||||||
emit(state.copyWith(status: CustomerFilesStatus.success));
|
emit(
|
||||||
|
state.copyWith(status: CustomerFilesStatus.success, selectedFiles: []),
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
|
|||||||
@@ -15,10 +15,7 @@ class UploadCustomerFileEvent extends CustomerFilesEvent {
|
|||||||
const UploadCustomerFileEvent({this.pickedFile, this.photo});
|
const UploadCustomerFileEvent({this.pickedFile, this.photo});
|
||||||
}
|
}
|
||||||
|
|
||||||
class DeleteCustomerFileEvent extends CustomerFilesEvent {
|
class DeleteCustomerFileEvent extends CustomerFilesEvent {}
|
||||||
final CustomerFileModel file;
|
|
||||||
const DeleteCustomerFileEvent(this.file);
|
|
||||||
}
|
|
||||||
|
|
||||||
class ToggleCustomerFileSelectionEvent extends CustomerFilesEvent {
|
class ToggleCustomerFileSelectionEvent extends CustomerFilesEvent {
|
||||||
final CustomerFileModel file;
|
final CustomerFileModel file;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flux/core/blocs/session/session_cubit.dart';
|
import 'package:flux/core/blocs/session/session_cubit.dart';
|
||||||
import 'package:flux/core/utils/functions.dart';
|
import 'package:flux/core/utils/functions.dart';
|
||||||
import 'package:flux/core/utils/string_extensions.dart';
|
import 'package:flux/core/utils/string_extensions.dart';
|
||||||
@@ -174,14 +175,31 @@ class CustomerRepository {
|
|||||||
.eq('id', id);
|
.eq('id', id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Elimina un file dallo storage
|
Future<void> deleteDocuments(List<CustomerFileModel> files) async {
|
||||||
Future<void> deleteDocument(CustomerFileModel file) async {
|
if (files.isEmpty) return;
|
||||||
|
|
||||||
|
// 1. Prepariamo le liste di ID e di Percorsi
|
||||||
|
final List<String> idsToDelete = files.map((f) => f.id!).toList();
|
||||||
|
final List<String> storagePaths = files.map((f) => f.storagePath).toList();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final path = await getSignedUrl(file.storagePath);
|
// 2. Cancellazione MASSIVA dal DB (una sola chiamata invece di un ciclo!)
|
||||||
await _supabase.from('customer_file').delete().eq('id', file.id!);
|
// .in_ dice: "cancella tutti i record il cui ID è contenuto in questa lista"
|
||||||
await _supabase.storage.from('documents').remove([path]);
|
await _supabase
|
||||||
} on Exception catch (e) {
|
.from('customer_file')
|
||||||
throw 'Errore durante l\'eliminazione del file: $e';
|
.delete()
|
||||||
|
.inFilter('id', idsToDelete);
|
||||||
|
|
||||||
|
// 3. Cancellazione MASSIVA dallo Storage
|
||||||
|
await _supabase.storage.from('documents').remove(storagePaths);
|
||||||
|
|
||||||
|
debugPrint("Eliminati con successo ${files.length} file.");
|
||||||
|
} on PostgrestException catch (e) {
|
||||||
|
debugPrint("Errore DB: ${e.message}");
|
||||||
|
throw 'Errore database: ${e.message}';
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint("Errore generico: $e");
|
||||||
|
throw 'Errore durante l\'eliminazione dei file: $e';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,9 +190,8 @@ class _CustomerDetailScreenState extends State<CustomerDetailScreen> {
|
|||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => QrUploadDialog(
|
builder: (context) => QrUploadDialog(
|
||||||
// L'URL dinamico che il telefono digerirà!
|
|
||||||
deepLinkUrl:
|
deepLinkUrl:
|
||||||
'fluxapp://customer/${widget.customer.id}?action=camera',
|
'fluxapp://customer/${widget.customer.id}/upload?name=${Uri.encodeComponent(widget.customer.nome)}',
|
||||||
title: 'Scatta per ${widget.customer.nome}',
|
title: 'Scatta per ${widget.customer.nome}',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user