visualizzazione file dei servizi e copia nei file del cliente

This commit is contained in:
2026-04-20 12:58:06 +02:00
parent 78012fdbf3
commit 8dc1c661ed
15 changed files with 397 additions and 72 deletions

View File

@@ -1,7 +1,10 @@
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flux/core/widgets/image_viewer_widget.dart';
import 'package:flux/core/widgets/pdf_viewer_widget.dart';
import 'package:flux/features/services/blocs/services_cubit.dart';
import 'package:flux/features/services/models/service_file_model.dart';
class AttachmentsSection extends StatelessWidget {
const AttachmentsSection({super.key});
@@ -24,7 +27,7 @@ class AttachmentsSection extends StatelessWidget {
Widget build(BuildContext context) {
return BlocBuilder<ServicesCubit, ServicesState>(
builder: (context, state) {
final localFiles = state.localAttachments;
final files = state.files;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -49,7 +52,7 @@ class AttachmentsSection extends StatelessWidget {
),
const SizedBox(height: 12),
if (localFiles.isEmpty)
if (files.isEmpty)
Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
@@ -71,42 +74,47 @@ class AttachmentsSection extends StatelessWidget {
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: localFiles.length,
itemCount: files.length,
itemBuilder: (context, index) {
final file = localFiles[index];
final file = files[index];
// Calcoliamo la dimensione in MB
final sizeMb = (file.size / (1024 * 1024)).toStringAsFixed(2);
final sizeMb = (file.fileSize / (1024 * 1024))
.toStringAsFixed(2);
// Scegliamo un'icona in base al tipo di file
final isPdf = file.extension?.toLowerCase() == 'pdf';
final isPdf = file.extension.toLowerCase() == 'pdf';
return Card(
margin: const EdgeInsets.only(bottom: 8),
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: BorderSide(color: Colors.grey.shade300),
),
child: ListTile(
leading: Icon(
isPdf ? Icons.picture_as_pdf : Icons.image,
color: isPdf ? Colors.red : Colors.blue,
size: 32,
return GestureDetector(
onTap: () => _handleSingleClick(context, file),
onDoubleTap: () => _handleDoubleClick(context, file),
child: Card(
margin: const EdgeInsets.only(bottom: 8),
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: BorderSide(color: Colors.grey.shade300),
),
title: Text(
file.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
subtitle: Text("$sizeMb MB"),
trailing: IconButton(
icon: const Icon(
Icons.delete_outline,
color: Colors.red,
child: ListTile(
leading: Icon(
isPdf ? Icons.picture_as_pdf : Icons.image,
color: isPdf ? Colors.red : Colors.blue,
size: 32,
),
title: Text(
file.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
subtitle: Text("$sizeMb MB"),
trailing: IconButton(
icon: const Icon(
Icons.delete_outline,
color: Colors.red,
),
onPressed: () => context
.read<ServicesCubit>()
.removeAttachment(index),
),
onPressed: () => context
.read<ServicesCubit>()
.removeLocalAttachment(index),
),
),
);
@@ -117,4 +125,54 @@ class AttachmentsSection extends StatelessWidget {
},
);
}
// --- LOGICA DI COPIA AL CLIENTE ---
void _handleSingleClick(BuildContext context, ServiceFileModel file) {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: const Text("Copia nei documenti Cliente"),
content: const Text(
"Vuoi copiare questo file nell'anagrafica del cliente? \n\n"
"Attenzione: per procedere, la pratica attuale verrà prima salvata in stato BOZZA.",
),
actions: [
TextButton(
onPressed: () => Navigator.pop(ctx),
child: const Text("Annulla"),
),
ElevatedButton(
onPressed: () {
Navigator.pop(ctx);
// 1. Diciamo al Cubit di salvare in Bozza e fare la copia
context.read<ServicesCubit>().saveAndCopyFileToCustomer(file);
},
child: const Text("Salva e Copia"),
),
],
),
);
}
// --- LOGICA DI VISUALIZZAZIONE OVERLAY ---
void _handleDoubleClick(BuildContext context, ServiceFileModel file) {
showDialog(
context: context,
barrierDismissible: true,
builder: (ctx) => Dialog(
insetPadding: const EdgeInsets.all(16),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height * 0.8,
child: file.isPdf
? PdfViewerWidget(url: file.url)
: ImageViewerWidget(url: file.url),
),
),
),
);
}
}