aggiunta scelta business o privato

This commit is contained in:
2026-05-19 11:54:59 +02:00
parent 2bdba523ad
commit 4e03d52a5d
11 changed files with 173 additions and 38 deletions

View File

@@ -64,11 +64,17 @@ class SharedCustomerSection extends StatelessWidget {
if (hasCustomer) ...[
const SizedBox(width: 12),
IconButton(
onPressed: () => context.pushNamed(
Routes.customerForm,
pathParameters: {'id': customer!.id!},
extra: customer,
),
onPressed: () async {
final updatedCustomer = await context.pushNamed(
Routes.customerForm,
pathParameters: {'id': customer!.id!},
extra: customer,
);
if (updatedCustomer != null &&
updatedCustomer is CustomerModel) {
onCustomerSelected(updatedCustomer);
}
},
icon: const Icon(Icons.edit),
),
],

View File

@@ -68,6 +68,7 @@ class CustomerFormCubit extends Cubit<CustomerFormState> {
String? email,
String? note,
bool? doNotDisturb,
bool? isBusiness,
}) {
emit(
state.copyWith(
@@ -77,6 +78,7 @@ class CustomerFormCubit extends Cubit<CustomerFormState> {
email: email ?? state.customer.email,
note: note ?? state.customer.note,
doNotDisturb: doNotDisturb ?? state.customer.doNotDisturb,
isBusiness: isBusiness ?? state.customer.isBusiness,
),
),
);
@@ -108,6 +110,7 @@ class CustomerFormCubit extends Cubit<CustomerFormState> {
required String name,
String? phone,
String? email,
required bool isBusiness,
}) async {
final newCustomer = CustomerModel(
name: name,
@@ -115,6 +118,7 @@ class CustomerFormCubit extends Cubit<CustomerFormState> {
email: email ?? '',
companyId: _sessionCubit.state.company!.id!,
note: '',
isBusiness: isBusiness,
);
try {

View File

@@ -14,6 +14,7 @@ class CustomerModel extends Equatable {
final String companyId; // UUID
final bool isActive;
final List<AttachmentModel> attachments;
final bool isBusiness;
const CustomerModel({
this.id,
@@ -27,6 +28,7 @@ class CustomerModel extends Equatable {
required this.companyId,
this.isActive = true,
this.attachments = const [],
this.isBusiness = false,
});
@override
@@ -42,6 +44,7 @@ class CustomerModel extends Equatable {
companyId,
isActive,
attachments,
isBusiness,
];
factory CustomerModel.empty() => CustomerModel(
@@ -65,6 +68,7 @@ class CustomerModel extends Equatable {
String? companyId,
bool? isActive,
List<AttachmentModel>? attachments,
bool? isBusiness,
}) {
return CustomerModel(
id: id ?? this.id,
@@ -78,6 +82,7 @@ class CustomerModel extends Equatable {
companyId: companyId ?? this.companyId,
isActive: isActive ?? this.isActive,
attachments: attachments ?? this.attachments,
isBusiness: isBusiness ?? this.isBusiness,
);
}
@@ -102,6 +107,7 @@ class CustomerModel extends Equatable {
?.map((x) => AttachmentModel.fromMap(x))
.toList() ??
const [],
isBusiness: map['is_business'] as bool? ?? false,
);
}
@@ -117,6 +123,7 @@ class CustomerModel extends Equatable {
'do_not_disturb': doNotDisturb,
'company_id': companyId,
'is_active': isActive,
'is_business': isBusiness,
};
}
}

View File

@@ -118,6 +118,38 @@ class _CustomerFormScreenState extends State<CustomerFormScreen> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
ChoiceChip(
label: const Text('Privato (Domestico)'),
selected: !state.customer.isBusiness,
selectedColor: Colors.blue.withValues(alpha: 0.2),
checkmarkColor: Colors.blue.shade700,
onSelected: (selected) {
if (selected) {
context.read<CustomerFormCubit>().updateFields(
isBusiness: false,
);
}
},
),
const SizedBox(width: 12),
ChoiceChip(
label: const Text('Business (P.IVA)'),
selected: state.customer.isBusiness,
selectedColor: Colors.orange.withValues(alpha: 0.2),
checkmarkColor: Colors.orange.shade700,
onSelected: (selected) {
if (selected) {
context.read<CustomerFormCubit>().updateFields(
isBusiness: true,
);
}
},
),
],
),
const Divider(height: 32),
FluxTextField(
label: 'Nome Completo',
autoFocus: true,

View File

@@ -16,6 +16,7 @@ class _QuickCustomerDialogState extends State<QuickCustomerDialog> {
final _phoneCtrl = TextEditingController();
final _emailCtrl = TextEditingController();
final _noteCtrl = TextEditingController();
bool _isBusiness = false; // Aggiungiamo un campo per il tipo di cliente
bool _isLoading = false;
@@ -45,6 +46,7 @@ class _QuickCustomerDialogState extends State<QuickCustomerDialog> {
final newCustomer = await context
.read<CustomerFormCubit>()
.quickCreateCustomer(
isBusiness: _isBusiness,
name: _nameCtrl.text.trim(),
phone: _phoneCtrl.text.trim(),
email: _emailCtrl.text.trim(),
@@ -65,6 +67,38 @@ class _QuickCustomerDialogState extends State<QuickCustomerDialog> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
ChoiceChip(
label: const Text('Privato (Domestico)'),
selected: _isBusiness == false,
selectedColor: Colors.blue.withValues(alpha: 0.2),
checkmarkColor: Colors.blue.shade700,
onSelected: (selected) {
if (selected) {
setState(() {
_isBusiness = false;
});
}
},
),
const SizedBox(width: 12),
ChoiceChip(
label: const Text('Business (P.IVA)'),
selected: _isBusiness == true,
selectedColor: Colors.orange.withValues(alpha: 0.2),
checkmarkColor: Colors.orange.shade700,
onSelected: (selected) {
if (selected) {
setState(() {
_isBusiness = true;
});
}
},
),
],
),
const Divider(height: 32),
TextField(
controller: _nameCtrl,
autofocus: true, // Focus immediato!

View File

@@ -206,6 +206,7 @@ class OperationFormCubit extends Cubit<OperationFormState> {
String? staffId,
String? staffDisplayName,
OperationStatus? status,
bool? isBusiness,
bool clearProvider = false,
bool clearType = false,
@@ -247,6 +248,7 @@ class OperationFormCubit extends Cubit<OperationFormState> {
staffId: staffId ?? current.staffId,
staffDisplayName: staffDisplayName ?? current.staffDisplayName,
status: status ?? current.status,
isBusiness: isBusiness ?? current.isBusiness,
);
emit(state.copyWith(operation: updated));

View File

@@ -48,6 +48,7 @@ class OperationModel extends Equatable {
final String? customerId;
final CustomerModel? customer;
final String reference;
final bool isBusiness;
// ALLEGATI (Aggiunto)
final List<AttachmentModel> attachments;
@@ -78,6 +79,7 @@ class OperationModel extends Equatable {
this.customer,
this.reference = '',
this.attachments = const [],
this.isBusiness = false,
});
OperationModel copyWith({
@@ -106,6 +108,7 @@ class OperationModel extends Equatable {
CustomerModel? customer,
String? reference,
List<AttachmentModel>? attachments,
bool? isBusiness,
}) => OperationModel(
id: id ?? this.id,
createdAt: createdAt ?? this.createdAt,
@@ -132,6 +135,7 @@ class OperationModel extends Equatable {
customer: customer ?? this.customer,
reference: reference ?? this.reference,
attachments: attachments ?? this.attachments,
isBusiness: isBusiness ?? this.isBusiness,
);
@override
@@ -161,6 +165,7 @@ class OperationModel extends Equatable {
customer,
reference,
attachments,
isBusiness,
];
factory OperationModel.empty() {
@@ -221,6 +226,7 @@ class OperationModel extends Equatable {
const [],
reference: map['reference'] as String? ?? '',
isBusiness: map['is_business'] as bool? ?? false,
);
}
@@ -245,6 +251,7 @@ class OperationModel extends Equatable {
'status': status.supabaseName,
if (customerId != null) 'customer_id': customerId,
'reference': reference,
'is_business': isBusiness,
};
}
}

View File

@@ -457,10 +457,11 @@ class _OperationFormScreenState extends State<OperationFormScreen> {
);
}).toList(),
onChanged: (newStatus) {
if (newStatus != null)
if (newStatus != null) {
context.read<OperationFormCubit>().updateFields(
status: newStatus,
);
}
},
),
),
@@ -482,6 +483,38 @@ class _OperationFormScreenState extends State<OperationFormScreen> {
icon: Icons.design_services,
themeColor: Colors.deepOrange,
children: [
Row(
children: [
ChoiceChip(
label: const Text('Privato (Domestico)'),
selected: !state.operation.isBusiness,
selectedColor: Colors.blue.withValues(alpha: 0.2),
checkmarkColor: Colors.blue.shade700,
onSelected: (selected) {
if (selected) {
context.read<OperationFormCubit>().updateFields(
isBusiness: false,
);
}
},
),
const SizedBox(width: 12),
ChoiceChip(
label: const Text('Business (P.IVA)'),
selected: state.operation.isBusiness,
selectedColor: Colors.orange.withValues(alpha: 0.2),
checkmarkColor: Colors.orange.shade700,
onSelected: (selected) {
if (selected) {
context.read<OperationFormCubit>().updateFields(
isBusiness: true,
);
}
},
),
],
),
const Divider(height: 32),
Wrap(
spacing: 8.0,
runSpacing: 8.0,
@@ -490,10 +523,11 @@ class _OperationFormScreenState extends State<OperationFormScreen> {
label: Text(type),
selected: state.operation.type == type,
onSelected: (selected) {
if (selected)
if (selected) {
context.read<OperationFormCubit>().setTypeWithSmartDefault(
type,
);
}
},
);
}).toList(),