From 4e03d52a5dc2ba441dffc5c24b01b5f3870b86e8 Mon Sep 17 00:00:00 2001 From: Mark M2 Macbook Date: Tue, 19 May 2026 11:54:59 +0200 Subject: [PATCH] aggiunta scelta business o privato --- .../shared_forms/customer_section.dart | 16 +++++--- .../customers/blocs/customer_form_cubit.dart | 4 ++ .../customers/models/customer_model.dart | 7 ++++ .../customers/ui/customer_form_screen.dart | 32 ++++++++++++++++ .../customers/ui/quick_customer_dialog.dart | 34 +++++++++++++++++ .../blocs/operation_form_cubit.dart | 2 + .../operations/models/operation_model.dart | 7 ++++ .../operations/ui/operation_form_screen.dart | 38 ++++++++++++++++++- macos/Podfile.lock | 31 --------------- macos/Runner.xcodeproj/project.pbxproj | 22 +++++++++++ .../xcshareddata/xcschemes/Runner.xcscheme | 18 +++++++++ 11 files changed, 173 insertions(+), 38 deletions(-) diff --git a/lib/core/widgets/shared_forms/customer_section.dart b/lib/core/widgets/shared_forms/customer_section.dart index d24fd49..0cc8956 100644 --- a/lib/core/widgets/shared_forms/customer_section.dart +++ b/lib/core/widgets/shared_forms/customer_section.dart @@ -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), ), ], diff --git a/lib/features/customers/blocs/customer_form_cubit.dart b/lib/features/customers/blocs/customer_form_cubit.dart index 1eae975..e46d7dc 100644 --- a/lib/features/customers/blocs/customer_form_cubit.dart +++ b/lib/features/customers/blocs/customer_form_cubit.dart @@ -68,6 +68,7 @@ class CustomerFormCubit extends Cubit { String? email, String? note, bool? doNotDisturb, + bool? isBusiness, }) { emit( state.copyWith( @@ -77,6 +78,7 @@ class CustomerFormCubit extends Cubit { 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 { required String name, String? phone, String? email, + required bool isBusiness, }) async { final newCustomer = CustomerModel( name: name, @@ -115,6 +118,7 @@ class CustomerFormCubit extends Cubit { email: email ?? '', companyId: _sessionCubit.state.company!.id!, note: '', + isBusiness: isBusiness, ); try { diff --git a/lib/features/customers/models/customer_model.dart b/lib/features/customers/models/customer_model.dart index 7f07a03..8562020 100644 --- a/lib/features/customers/models/customer_model.dart +++ b/lib/features/customers/models/customer_model.dart @@ -14,6 +14,7 @@ class CustomerModel extends Equatable { final String companyId; // UUID final bool isActive; final List 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? 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, }; } } diff --git a/lib/features/customers/ui/customer_form_screen.dart b/lib/features/customers/ui/customer_form_screen.dart index 6f61e86..788019b 100644 --- a/lib/features/customers/ui/customer_form_screen.dart +++ b/lib/features/customers/ui/customer_form_screen.dart @@ -118,6 +118,38 @@ class _CustomerFormScreenState extends State { 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().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().updateFields( + isBusiness: true, + ); + } + }, + ), + ], + ), + const Divider(height: 32), FluxTextField( label: 'Nome Completo', autoFocus: true, diff --git a/lib/features/customers/ui/quick_customer_dialog.dart b/lib/features/customers/ui/quick_customer_dialog.dart index 60de695..45dfcb6 100644 --- a/lib/features/customers/ui/quick_customer_dialog.dart +++ b/lib/features/customers/ui/quick_customer_dialog.dart @@ -16,6 +16,7 @@ class _QuickCustomerDialogState extends State { 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 { final newCustomer = await context .read() .quickCreateCustomer( + isBusiness: _isBusiness, name: _nameCtrl.text.trim(), phone: _phoneCtrl.text.trim(), email: _emailCtrl.text.trim(), @@ -65,6 +67,38 @@ class _QuickCustomerDialogState extends State { 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! diff --git a/lib/features/operations/blocs/operation_form_cubit.dart b/lib/features/operations/blocs/operation_form_cubit.dart index 622460c..726d4e4 100644 --- a/lib/features/operations/blocs/operation_form_cubit.dart +++ b/lib/features/operations/blocs/operation_form_cubit.dart @@ -206,6 +206,7 @@ class OperationFormCubit extends Cubit { String? staffId, String? staffDisplayName, OperationStatus? status, + bool? isBusiness, bool clearProvider = false, bool clearType = false, @@ -247,6 +248,7 @@ class OperationFormCubit extends Cubit { staffId: staffId ?? current.staffId, staffDisplayName: staffDisplayName ?? current.staffDisplayName, status: status ?? current.status, + isBusiness: isBusiness ?? current.isBusiness, ); emit(state.copyWith(operation: updated)); diff --git a/lib/features/operations/models/operation_model.dart b/lib/features/operations/models/operation_model.dart index df88f7b..94b3c4f 100644 --- a/lib/features/operations/models/operation_model.dart +++ b/lib/features/operations/models/operation_model.dart @@ -48,6 +48,7 @@ class OperationModel extends Equatable { final String? customerId; final CustomerModel? customer; final String reference; + final bool isBusiness; // ALLEGATI (Aggiunto) final List 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? 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, }; } } diff --git a/lib/features/operations/ui/operation_form_screen.dart b/lib/features/operations/ui/operation_form_screen.dart index 21e988e..55b97c0 100644 --- a/lib/features/operations/ui/operation_form_screen.dart +++ b/lib/features/operations/ui/operation_form_screen.dart @@ -457,10 +457,11 @@ class _OperationFormScreenState extends State { ); }).toList(), onChanged: (newStatus) { - if (newStatus != null) + if (newStatus != null) { context.read().updateFields( status: newStatus, ); + } }, ), ), @@ -482,6 +483,38 @@ class _OperationFormScreenState extends State { 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().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().updateFields( + isBusiness: true, + ); + } + }, + ), + ], + ), + const Divider(height: 32), Wrap( spacing: 8.0, runSpacing: 8.0, @@ -490,10 +523,11 @@ class _OperationFormScreenState extends State { label: Text(type), selected: state.operation.type == type, onSelected: (selected) { - if (selected) + if (selected) { context.read().setTypeWithSmartDefault( type, ); + } }, ); }).toList(), diff --git a/macos/Podfile.lock b/macos/Podfile.lock index e5e7fa5..1685c88 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -1,58 +1,27 @@ PODS: - - app_links (6.4.1): - - FlutterMacOS - - file_picker (0.0.1): - - FlutterMacOS - - file_selector_macos (0.0.1): - - FlutterMacOS - FlutterMacOS (1.0.0) - pdfx (1.0.0): - FlutterMacOS - printing (1.0.0): - FlutterMacOS - - shared_preferences_foundation (0.0.1): - - Flutter - - FlutterMacOS - - url_launcher_macos (0.0.1): - - FlutterMacOS DEPENDENCIES: - - app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`) - - file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`) - - file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - pdfx (from `Flutter/ephemeral/.symlinks/plugins/pdfx/macos`) - printing (from `Flutter/ephemeral/.symlinks/plugins/printing/macos`) - - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) EXTERNAL SOURCES: - app_links: - :path: Flutter/ephemeral/.symlinks/plugins/app_links/macos - file_picker: - :path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos - file_selector_macos: - :path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos FlutterMacOS: :path: Flutter/ephemeral pdfx: :path: Flutter/ephemeral/.symlinks/plugins/pdfx/macos printing: :path: Flutter/ephemeral/.symlinks/plugins/printing/macos - shared_preferences_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin - url_launcher_macos: - :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos SPEC CHECKSUMS: - app_links: 05a6ec2341985eb05e9f97dc63f5837c39895c3f - file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a - file_selector_macos: 9e9e068e90ebee155097d00e89ae91edb2374db7 FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 pdfx: 1e79f57f7a6ce2f4a4c30f21fa54d3dc82441b51 printing: c4cf83c78fd684f9bc318e6aadc18972aa48f617 - shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb - url_launcher_macos: f87a979182d112f911de6820aefddaf56ee9fbfd PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index a71cfcd..1d3d986 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -29,6 +29,7 @@ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 47B861EC08643C31319819EE /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AD6F0633B38D7C51DB0A44A /* Pods_RunnerTests.framework */; }; BC7B14BF366111D5491A16DE /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9C1847336C291D2358A2A03 /* Pods_Runner.framework */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -88,6 +89,7 @@ EF12DE99A4F7A47E54D9243F /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; F673AA005B814BAB5FA49C69 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; F9C1847336C291D2358A2A03 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -103,6 +105,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, BC7B14BF366111D5491A16DE /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -164,6 +167,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, @@ -231,6 +235,9 @@ productType = "com.apple.product-type.bundle.unit-test"; }; 33CC10EC2044A3C60003C045 /* Runner */ = { + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( @@ -256,6 +263,9 @@ /* Begin PBXProject section */ 33CC10E52044A3C60003C045 /* Project object */ = { + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, + ); isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; @@ -796,6 +806,18 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 33CC10E52044A3C60003C045 /* Project object */; } diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 6231b63..9cb6c64 100644 --- a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -5,6 +5,24 @@ + + + + + + + + + +