import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/features/attachments/blocs/operation_files_bloc.dart'; import 'package:image_picker/image_picker.dart'; import 'package:file_picker/file_picker.dart'; class OperationMobileUploadScreen extends StatefulWidget { final String operationId; final String operationName; const OperationMobileUploadScreen({ super.key, required this.operationId, required this.operationName, }); @override State createState() => _OperationMobileUploadScreenState(); } class _OperationMobileUploadScreenState extends State { // 1. LA NOSTRA STAGING AREA (Il "Carrello") final List _stagedFiles = []; // 2. STATO DI CARICAMENTO GLOBALE bool _isUploading = false; // Funzione magica per capire se è un'immagine o un PDF dall'estensione bool _isImage(String path) { final ext = path.split('.').last.toLowerCase(); return ['jpg', 'jpeg', 'png', 'webp'].contains(ext); } @override Widget build(BuildContext context) { return BlocListener( listener: (context, state) { // Quando il BLoC ci dice che ha finito l'upload (Success), chiudiamo la pagina! if (state.status == OperationFilesStatus.success && _isUploading) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text("Tutti i file caricati con successo! ✅"), ), ); Navigator.of(context).pop(); } if (state.status == OperationFilesStatus.failure) { setState(() => _isUploading = false); ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text("Errore: ${state.error}"))); } }, child: Scaffold( appBar: AppBar( title: Text("Upload Pratica:\n${widget.operationName}"), automaticallyImplyLeading: !_isUploading, ), body: Stack( children: [ Column( children: [ // --- SEZIONE PULSANTI (Fotocamera / Galleria) --- Padding( padding: const EdgeInsets.all(16.0), child: Row( children: [ Expanded( child: ElevatedButton.icon( onPressed: _isUploading ? null : _handleCamera, icon: const Icon(Icons.camera_alt), label: const Text("SCATTA"), style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), ), ), ), const SizedBox(width: 12), Expanded( child: OutlinedButton.icon( onPressed: _isUploading ? null : _handleFilePicker, icon: const Icon(Icons.folder), label: const Text("GALLERIA"), style: OutlinedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), ), ), ), ], ), ), const Divider(), // --- SEZIONE ANTEPRIME (La GridView Magica) --- Expanded( child: _stagedFiles.isEmpty ? const Center( child: Text( "Nessun file selezionato.\nScatta una foto o scegli dalla galleria.", textAlign: TextAlign.center, style: TextStyle(color: Colors.grey), ), ) : GridView.builder( padding: const EdgeInsets.all(16), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, // 3 colonne come la galleria dell'iPhone crossAxisSpacing: 12, mainAxisSpacing: 12, ), itemCount: _stagedFiles.length, itemBuilder: (context, index) { final file = _stagedFiles[index]; final isImg = _isImage(file.name); return Stack( clipBehavior: Clip.none, children: [ // L'ANTEPRIMA Container( width: double.infinity, height: double.infinity, decoration: BoxDecoration( color: Colors.grey.shade200, borderRadius: BorderRadius.circular(12), border: Border.all( color: Colors.grey.shade300, ), ), child: ClipRRect( borderRadius: BorderRadius.circular(12), child: isImg ? Image.file( File(file.path!), fit: BoxFit.cover, ) : const Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.picture_as_pdf, color: Colors.red, size: 36, ), SizedBox(height: 4), Text( "PDF", style: TextStyle( fontSize: 10, fontWeight: FontWeight.bold, ), ), ], ), ), ), // IL PULSANTE CESTINO (In alto a destra) Positioned( top: -8, right: -8, child: GestureDetector( onTap: () { setState(() { _stagedFiles.removeAt(index); }); }, child: Container( padding: const EdgeInsets.all(4), decoration: const BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), child: const Icon( Icons.close, color: Colors.white, size: 16, ), ), ), ), ], ); }, ), ), // --- SEZIONE INVIA E CHIUDI --- SafeArea( child: Padding( padding: const EdgeInsets.all(16.0), child: SizedBox( width: double.infinity, height: 56, child: ElevatedButton.icon( // Il pulsante si accende SOLO se ci sono file nel carrello onPressed: _stagedFiles.isEmpty || _isUploading ? null : _submitAllFiles, icon: const Icon(Icons.cloud_upload), label: Text( "INVIA ${_stagedFiles.length} FILE E CHIUDI", style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), style: ElevatedButton.styleFrom( backgroundColor: Theme.of( context, ).colorScheme.primary, foregroundColor: Theme.of( context, ).colorScheme.onPrimary, ), ), ), ), ), ], ), // --- OVERLAY DI CARICAMENTO (Impedisce tap multipli) --- if (_isUploading) Container( color: Colors.black.withValues(alpha: 0.5), child: const Center( child: Card( child: Padding( padding: EdgeInsets.all(24.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ CircularProgressIndicator(), SizedBox(height: 16), Text( "Caricamento in corso...", style: TextStyle(fontWeight: FontWeight.bold), ), ], ), ), ), ), ), ], ), ), ); } // --- LOGICA FOTOCAMERA E LIBRERIA --- Future _handleCamera() async { final picker = ImagePicker(); final photo = await picker.pickImage( source: ImageSource.camera, imageQuality: 80, ); if (photo != null) { final photoBytes = await photo.readAsBytes(); // Sicuro anche per Web! final photoSize = await photo.length(); final platformFile = PlatformFile( name: photo.name, size: photoSize, path: photo.path, bytes: photoBytes, // I bytes ci salvano la vita su Supabase! ); setState(() { _stagedFiles.add(platformFile); // Unifichiamo tutto in un dart:io File }); } } Future _handleFilePicker() async { // allowMultiple: true permette di pescare 5 foto dalla galleria in un colpo solo! final result = await FilePicker.pickFiles(allowMultiple: true); if (result != null) { setState(() { _stagedFiles.addAll(result.files); }); } } // --- LOGICA DI INVIO AL BLoC --- void _submitAllFiles() { setState(() => _isUploading = true); // Diciamo al BLoC di caricare tutti i file. // Usiamo il tuo evento esistente per ogni file (il BLoC li metterà in coda) final bloc = context.read(); bloc.add(UploadOperationFilesEvent(pickedFiles: _stagedFiles)); // N.B: Il Navigator.pop() viene chiamato dal BlocListener in alto quando lo stato diventa "success"! } }