feat-add-files-from-qr #8

Merged
brontomark merged 13 commits from feat-add-files-from-qr into main 2026-04-26 10:15:35 +02:00
4 changed files with 33 additions and 17 deletions
Showing only changes of commit a52436ea9a - Show all commits

View File

@@ -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(

View File

@@ -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;

View 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';
} }
} }
} }

View File

@@ -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}',
), ),
); );