sistemati ticket
This commit is contained in:
@@ -1,24 +1,27 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flux/core/routes/routes.dart';
|
||||
import 'package:flux/features/customers/blocs/customers_cubit.dart';
|
||||
import 'package:flux/features/customers/models/customer_model.dart';
|
||||
import 'package:flux/features/customers/ui/quick_customer_dialog.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class SharedCustomerSection extends StatelessWidget {
|
||||
final String? customerId;
|
||||
final String? customerName;
|
||||
final CustomerModel? customer;
|
||||
final ValueChanged<CustomerModel> onCustomerSelected;
|
||||
|
||||
const SharedCustomerSection({
|
||||
super.key,
|
||||
this.customerId,
|
||||
this.customerName,
|
||||
this.customer,
|
||||
required this.onCustomerSelected,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final hasCustomer = customerId != null && customerId!.isNotEmpty;
|
||||
final hasCustomer = customer != null && customer!.id!.isNotEmpty;
|
||||
final theme = Theme.of(context);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -47,7 +50,7 @@ class SharedCustomerSection extends StatelessWidget {
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
hasCustomer ? customerName! : 'Seleziona Cliente *',
|
||||
hasCustomer ? customer!.name : 'Seleziona Cliente *',
|
||||
style: TextStyle(
|
||||
fontWeight: hasCustomer
|
||||
? FontWeight.bold
|
||||
@@ -57,10 +60,145 @@ class SharedCustomerSection extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const Icon(Icons.search),
|
||||
|
||||
if (hasCustomer) ...[
|
||||
const SizedBox(width: 12),
|
||||
IconButton(
|
||||
onPressed: () => context.pushNamed(
|
||||
Routes.customerForm,
|
||||
pathParameters: {'id': customer!.id!},
|
||||
extra: customer,
|
||||
),
|
||||
icon: const Icon(Icons.edit),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (hasCustomer &&
|
||||
(customer!.phoneNumber.isNotEmpty ||
|
||||
customer!.email.isNotEmpty)) ...[
|
||||
const SizedBox(height: 12), // Un po' più di respiro dal box sopra
|
||||
// Mettiamo i contatti in un Container con un po' di stile per farli sembrare una "Contact Card" integrata
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.withValues(alpha: 0.05), // Sfondo leggerissimo
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: Colors.grey.withValues(alpha: 0.2)),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// --- RIGA TELEFONO ---
|
||||
if (customer!.phoneNumber.isNotEmpty)
|
||||
Row(
|
||||
children: [
|
||||
// Usiamo i pulsanti "Small" per non occupare troppo spazio verticale
|
||||
IconButton(
|
||||
visualDensity: VisualDensity.compact,
|
||||
onPressed: () => launchUrl(
|
||||
Uri.parse('https://wa.me/39${customer!.phoneNumber}'),
|
||||
),
|
||||
icon: const FaIcon(
|
||||
FontAwesomeIcons.whatsapp,
|
||||
color: Colors.green,
|
||||
size: 20,
|
||||
),
|
||||
tooltip: 'Invia WhatsApp',
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
// Expanded evita l'overflow se il numero è assurdamente lungo
|
||||
child: SelectableText(
|
||||
customer!.phoneNumber,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
visualDensity: VisualDensity.compact,
|
||||
onPressed: () {
|
||||
Clipboard.setData(
|
||||
ClipboardData(text: customer!.phoneNumber),
|
||||
);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Telefono copiato!'),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.copy,
|
||||
size: 18,
|
||||
color: Colors.grey,
|
||||
),
|
||||
tooltip: 'Copia',
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// Sezione divisoria se ci sono entrambi
|
||||
if (customer!.phoneNumber.isNotEmpty &&
|
||||
customer!.email.isNotEmpty)
|
||||
const Divider(height: 8, thickness: 0.5),
|
||||
|
||||
// --- RIGA EMAIL ---
|
||||
if (customer!.email.isNotEmpty)
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
visualDensity: VisualDensity.compact,
|
||||
onPressed: () => launchUrl(
|
||||
Uri.parse('mailto:${customer!.email}'),
|
||||
), // Rimosso il // dopo mailto:, è più sicuro
|
||||
icon: const FaIcon(
|
||||
FontAwesomeIcons.envelope,
|
||||
color: Colors.blue,
|
||||
size: 20,
|
||||
),
|
||||
tooltip: 'Invia Email',
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
// L'Expanded è vitale per le email che possono essere lunghissime
|
||||
child: SelectableText(
|
||||
customer!.email,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
visualDensity: VisualDensity.compact,
|
||||
onPressed: () {
|
||||
Clipboard.setData(
|
||||
ClipboardData(text: customer!.email),
|
||||
);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Email copiata!'),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.copy,
|
||||
size: 18,
|
||||
color: Colors.grey,
|
||||
),
|
||||
tooltip: 'Copia',
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ class SharedModelSection extends StatelessWidget {
|
||||
final String? modelId;
|
||||
final String? modelName;
|
||||
final String label;
|
||||
final Color? backgroundColor;
|
||||
final Color? borderColor;
|
||||
|
||||
// Usiamo una callback che passa direttamente ID e Nome
|
||||
// così non dobbiamo preoccuparci di importare la classe esatta del modello ovunque
|
||||
@@ -18,6 +20,8 @@ class SharedModelSection extends StatelessWidget {
|
||||
required this.modelName,
|
||||
required this.onModelSelected,
|
||||
this.label = 'Seleziona Modello',
|
||||
this.backgroundColor,
|
||||
this.borderColor,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -26,6 +30,7 @@ class SharedModelSection extends StatelessWidget {
|
||||
final hasModel = modelId != null && modelId!.isNotEmpty;
|
||||
|
||||
return ListTile(
|
||||
tileColor: backgroundColor,
|
||||
title: Text(label),
|
||||
subtitle: Text(
|
||||
hasModel ? modelName! : 'Nessun modello selezionato',
|
||||
@@ -36,7 +41,7 @@ class SharedModelSection extends StatelessWidget {
|
||||
),
|
||||
trailing: const Icon(Icons.arrow_drop_down),
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(color: theme.dividerColor),
|
||||
side: BorderSide(color: borderColor ?? theme.dividerColor),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
onTap: () => _showModelModal(context),
|
||||
|
||||
Reference in New Issue
Block a user