aggiunto colore e files a ticket form

This commit is contained in:
2026-05-07 10:30:37 +02:00
parent c6321d6580
commit c8d6d4470c
3 changed files with 557 additions and 287 deletions

View File

@@ -0,0 +1,175 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flux/core/widgets/shared_forms/mobile_upload_screen.dart';
// Adatta gli import alle tue cartelle reali!
import 'package:flux/features/attachments/blocs/attachments_bloc.dart';
class SharedFilesSection extends StatelessWidget {
final String
titleNameForUpload; // Es. il nome del cliente o il modello da passare alla pagina di upload
const SharedFilesSection({super.key, required this.titleNameForUpload});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Allegati e Foto',
style: TextStyle(fontWeight: FontWeight.bold),
),
TextButton.icon(
icon: const Icon(Icons.add_a_photo),
label: const Text('Aggiungi'),
onPressed: () {
// Navighiamo verso la nostra fiammante pagina di upload agnostica!
// Assicurati che l'AttachmentsBloc sopravviva al cambio pagina usando BlocProvider.value
final bloc = context.read<AttachmentsBloc>();
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => BlocProvider.value(
value: bloc,
child: SharedMobileUploadScreen(
title: titleNameForUpload,
),
),
),
);
},
),
],
),
const SizedBox(height: 8),
// LA VETRINA DEI FILE
BlocBuilder<AttachmentsBloc, AttachmentsState>(
builder: (context, state) {
final files =
state.allFiles; // Unisce sia i remoti che i locali (bozze)
if (state.status == AttachmentsStatus.loading) {
return const Center(child: CircularProgressIndicator());
}
if (files.isEmpty) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: theme.colorScheme.surface,
border: Border.all(
color: theme.dividerColor,
style: BorderStyle.solid,
),
borderRadius: BorderRadius.circular(12),
),
child: const Column(
children: [
Icon(
Icons.image_not_supported_outlined,
color: Colors.grey,
size: 32,
),
SizedBox(height: 8),
Text(
'Nessun file allegato',
style: TextStyle(color: Colors.grey),
),
],
),
);
}
return Wrap(
spacing: 12,
runSpacing: 12,
children: files.map((file) {
final isImage = [
'jpg',
'jpeg',
'png',
'webp',
].contains(file.extension.toLowerCase());
return Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: theme.colorScheme.surface,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: theme.dividerColor),
),
child: Stack(
children: [
// Sfondo File / Anteprima
Center(
child: isImage
? const Icon(
Icons.image,
color: Colors.blue,
size: 40,
) // Qui in futuro metteremo Image.network da Supabase
: const Icon(
Icons.picture_as_pdf,
color: Colors.red,
size: 40,
),
),
// Indicatore "Bozza" per i file non ancora caricati
if (file.id == null)
Positioned(
bottom: 4,
left: 4,
right: 4,
child: Container(
padding: const EdgeInsets.symmetric(vertical: 2),
decoration: BoxDecoration(
color: Colors.orange,
borderRadius: BorderRadius.circular(4),
),
child: const Text(
'Da salvare',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 8,
fontWeight: FontWeight.bold,
),
),
),
),
// Pulsante Elimina
Positioned(
top: -8,
right: -8,
child: IconButton(
icon: const Icon(
Icons.cancel,
color: Colors.redAccent,
size: 20,
),
onPressed: () {
// Manda l'evento di eliminazione
context.read<AttachmentsBloc>().add(
DeleteSpecificAttachmentEvent(file),
);
},
),
),
],
),
);
}).toList(),
);
},
),
],
);
}
}