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 73 additions and 14 deletions
Showing only changes of commit de431b6ee6 - Show all commits

View File

@@ -128,7 +128,29 @@ class ServiceFilesBloc extends Bloc<ServiceFilesEvent, ServiceFilesState> {
FutureOr<void> _onUploadServiceFiles( FutureOr<void> _onUploadServiceFiles(
UploadServiceFilesEvent event, UploadServiceFilesEvent event,
Emitter<ServiceFilesState> emit, Emitter<ServiceFilesState> emit,
) {} ) async {
if (event.pickedFiles == null && event.photos == null) return;
if (event.pickedFiles!.isEmpty && event.photos!.isEmpty) return;
// BIVIO 2: PRATICA ESISTENTE (Abbiamo l'ID
emit(state.copyWith(status: ServiceFilesStatus.uploading));
try {
// Logica identica a quella che abbiamo fatto per i clienti
if (event.pickedFiles != null && event.pickedFiles!.isNotEmpty) {
for (var file in event.pickedFiles!) {
await _repository.uploadAndRegisterServiceFile(
serviceId: serviceId!,
pickedFile: file,
);
}
}
emit(state.copyWith(status: ServiceFilesStatus.success));
} catch (e) {
emit(
state.copyWith(status: ServiceFilesStatus.failure, error: e.toString()),
);
}
}
FutureOr<void> _onDeleteServiceFiles( FutureOr<void> _onDeleteServiceFiles(
DeleteServiceFilesEvent event, DeleteServiceFilesEvent event,

View File

@@ -33,12 +33,12 @@ class AddServiceFilesEvent extends ServiceFilesEvent {
} }
class UploadServiceFilesEvent extends ServiceFilesEvent { class UploadServiceFilesEvent extends ServiceFilesEvent {
final PlatformFile? pickedFile; final List<PlatformFile>? pickedFiles;
final File? photo; final List<File>? photos;
const UploadServiceFilesEvent({this.pickedFile, this.photo}); const UploadServiceFilesEvent({this.pickedFiles, this.photos});
@override @override
List<Object?> get props => [pickedFile, photo]; List<Object?> get props => [pickedFiles, photos];
} }
class DeleteServiceFilesEvent extends ServiceFilesEvent {} class DeleteServiceFilesEvent extends ServiceFilesEvent {}

View File

@@ -308,7 +308,7 @@ class AttachmentsSection extends StatelessWidget {
}, },
child: QrUploadDialog( child: QrUploadDialog(
deepLinkUrl: deepLinkUrl:
'fluxapp://service/${currentService!.id}/upload?name=${Uri.encodeComponent(nomePratica)}', 'fluxapp:///service/${currentService!.id}/upload?name=${Uri.encodeComponent(nomePratica)}',
title: 'Scatta per\n$nomePratica', title: 'Scatta per\n$nomePratica',
), ),
), ),

View File

@@ -5,7 +5,7 @@ import 'package:image_picker/image_picker.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:flux/features/services/blocs/service_files_bloc.dart'; import 'package:flux/features/services/blocs/service_files_bloc.dart';
class ServiceMobileUploadScreen extends StatelessWidget { class ServiceMobileUploadScreen extends StatefulWidget {
final String serviceId; final String serviceId;
final String serviceName; final String serviceName;
@@ -15,6 +15,15 @@ class ServiceMobileUploadScreen extends StatelessWidget {
required this.serviceName, required this.serviceName,
}); });
@override
State<ServiceMobileUploadScreen> createState() =>
_ServiceMobileUploadScreenState();
}
class _ServiceMobileUploadScreenState extends State<ServiceMobileUploadScreen> {
final List<PlatformFile> _pickedFiles = [];
final List<File> _photos = [];
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocListener<ServiceFilesBloc, ServiceFilesState>( return BlocListener<ServiceFilesBloc, ServiceFilesState>(
@@ -31,7 +40,7 @@ class ServiceMobileUploadScreen extends StatelessWidget {
} }
}, },
child: Scaffold( child: Scaffold(
appBar: AppBar(title: Text("Upload Pratica:\n$serviceName")), appBar: AppBar(title: Text("Upload Pratica:\n${widget.serviceName}")),
body: Padding( body: Padding(
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.all(24.0),
child: Column( child: Column(
@@ -74,6 +83,27 @@ class ServiceMobileUploadScreen extends StatelessWidget {
), ),
), ),
), ),
const SizedBox(height: 30),
SizedBox(
width: double.infinity,
height: 80,
child: ElevatedButton.icon(
onPressed: () => _handleSaveAndClose(context),
icon: const Icon(Icons.save_alt_rounded, size: 28),
label: const Text(
"INVIA E CHIUDI",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.grey[200],
foregroundColor: Colors.black87,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
),
),
),
], ],
), ),
), ),
@@ -88,18 +118,25 @@ class ServiceMobileUploadScreen extends StatelessWidget {
imageQuality: 80, imageQuality: 80,
); );
if (photo != null && context.mounted) { if (photo != null && context.mounted) {
context.read<ServiceFilesBloc>().add( setState(() {
UploadServiceFilesEvent(photo: File(photo.path)), _photos.add(File(photo.path));
); });
} }
} }
Future<void> _handleFilePicker(BuildContext context) async { Future<void> _handleFilePicker(BuildContext context) async {
final result = await FilePicker.pickFiles(withData: true); final result = await FilePicker.pickFiles(withData: true);
if (result != null && context.mounted) { if (result != null && context.mounted) {
context.read<ServiceFilesBloc>().add( setState(() {
UploadServiceFilesEvent(pickedFile: result.files.first), _pickedFiles.addAll(result.files);
); });
} }
} }
Future<void> _handleSaveAndClose(BuildContext context) async {
context.read<ServiceFilesBloc>().add(
UploadServiceFilesEvent(pickedFiles: _pickedFiles, photos: _photos),
);
Navigator.pop(context);
}
} }