diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index e4ef43f..87b6bad 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip +distributionUrl=https\://operations.gradle.org/distributions/gradle-8.14-all.zip diff --git a/lib/core/routes/app_router.dart b/lib/core/routes/app_router.dart index be1f6ed..aaed4d9 100644 --- a/lib/core/routes/app_router.dart +++ b/lib/core/routes/app_router.dart @@ -131,7 +131,7 @@ class AppRouter { ), ), GoRoute( - path: '/services', + path: '/operations', builder: (context, state) => const ServicesScreen(), ), GoRoute( @@ -168,8 +168,8 @@ class AppRouter { }, ), GoRoute( - path: '/service-form', - name: 'service-form', + path: '/operation-form', + name: 'operation-form', builder: (context, state) { final existingService = state.extra as ServiceModel?; final serviceId = state.uri.queryParameters['serviceId']; @@ -184,7 +184,7 @@ class AppRouter { }, ), GoRoute( - path: '/service/:id/upload', + path: '/operation/:id/upload', builder: (context, state) { final serviceId = state.pathParameters['id']!; final serviceName = state.uri.queryParameters['name'] ?? 'Pratica'; diff --git a/lib/core/widgets/flux_text_field.dart b/lib/core/widgets/flux_text_field.dart index f2cbf24..39fcf8c 100644 --- a/lib/core/widgets/flux_text_field.dart +++ b/lib/core/widgets/flux_text_field.dart @@ -1,6 +1,6 @@ // lib/ui/common/flux_text_field.dart import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; +import 'package:flutter/operations.dart'; import 'package:flux/core/theme/theme.dart'; class FluxTextField extends StatefulWidget { diff --git a/lib/features/customers/ui/customer_search_sheet.dart b/lib/features/customers/ui/customer_search_sheet.dart index c12609c..0030995 100644 --- a/lib/features/customers/ui/customer_search_sheet.dart +++ b/lib/features/customers/ui/customer_search_sheet.dart @@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/features/customers/blocs/customer_cubit.dart'; import 'package:flux/features/customers/models/customer_model.dart'; import 'package:flux/features/customers/ui/quick_customer_dialog.dart'; -import 'package:flux/features/operations/blocs/services_cubit.dart'; +import 'package:flux/features/operations/blocs/operations_cubit.dart'; class CustomerSearchSheet extends StatefulWidget { const CustomerSearchSheet({super.key}); diff --git a/lib/features/home/latest_store_services/bloc/latest_store_services_bloc.dart b/lib/features/home/latest_store_services/bloc/latest_store_services_bloc.dart index a85c6c9..b80cfd7 100644 --- a/lib/features/home/latest_store_services/bloc/latest_store_services_bloc.dart +++ b/lib/features/home/latest_store_services/bloc/latest_store_services_bloc.dart @@ -29,10 +29,10 @@ class LatestStoreServicesBloc // Questo gira ad ogni "scatto" dello stream di Supabase List fullyHydratedServices = []; - for (ServiceModel service in rawServices) { + for (ServiceModel operation in rawServices) { // Peschiamo i dati completi (incluso il cliente) ServiceModel fullService = await _repository.fetchServiceById( - service.id!, + operation.id!, ); fullyHydratedServices.add(fullService); } @@ -47,7 +47,7 @@ class LatestStoreServicesBloc onData: (List fullyHydratedServices) { // Qui ora è tutto sincrono e bellissimo return state.copyWith( - services: fullyHydratedServices, + operations: fullyHydratedServices, status: LatestStoreServicesStatus.success, ); }, diff --git a/lib/features/home/latest_store_services/bloc/latest_store_services_state.dart b/lib/features/home/latest_store_services/bloc/latest_store_services_state.dart index ede49cb..8c9907d 100644 --- a/lib/features/home/latest_store_services/bloc/latest_store_services_state.dart +++ b/lib/features/home/latest_store_services/bloc/latest_store_services_state.dart @@ -5,26 +5,26 @@ enum LatestStoreServicesStatus { initial, loading, success, failure } class LatestStoreServicesState extends Equatable { final LatestStoreServicesStatus status; final String? error; - final List services; + final List operations; const LatestStoreServicesState({ required this.status, this.error, - this.services = const [], + this.operations = const [], }); @override - List get props => [status, error, services]; + List get props => [status, error, operations]; LatestStoreServicesState copyWith({ LatestStoreServicesStatus? status, String? error, - List? services, + List? operations, }) { return LatestStoreServicesState( status: status ?? this.status, error: error, - services: services ?? this.services, + operations: operations ?? this.operations, ); } } diff --git a/lib/features/home/latest_store_services/ui/latest_store_services_card.dart b/lib/features/home/latest_store_services/ui/latest_store_services_card.dart index 368b7dc..bf8556c 100644 --- a/lib/features/home/latest_store_services/ui/latest_store_services_card.dart +++ b/lib/features/home/latest_store_services/ui/latest_store_services_card.dart @@ -70,7 +70,7 @@ class _LatestServicesCardContent extends StatelessWidget { const SizedBox(width: 12), Expanded( child: TextButton( - onPressed: () => context.push('/services'), + onPressed: () => context.push('/operations'), child: Text( context.l10n.homeLatestServices, style: TextStyle( @@ -105,7 +105,7 @@ class _LatestServicesCardContent extends StatelessWidget { ); } - if (state.services.isEmpty) { + if (state.operations.isEmpty) { return Center( child: Text( "Nessun servizio recente.", @@ -118,16 +118,16 @@ class _LatestServicesCardContent extends StatelessWidget { } return ListView.separated( - itemCount: state.services.length, + itemCount: state.operations.length, separatorBuilder: (context, index) => Divider( height: 1, color: theme.dividerColor.withValues(alpha: 0.3), ), itemBuilder: (context, index) { - final service = state.services[index]; + final operation = state.operations[index]; return InkWell( onTap: () => - context.push('/service-form', extra: service), + context.push('/operation-form', extra: operation), child: Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( @@ -136,7 +136,7 @@ class _LatestServicesCardContent extends StatelessWidget { Expanded( flex: 5, child: Text( - service.customerDisplayName ?? + operation.customerDisplayName ?? 'Cliente sconosciuto', style: TextStyle( fontWeight: FontWeight.w700, @@ -147,7 +147,7 @@ class _LatestServicesCardContent extends StatelessWidget { Expanded( flex: 5, child: Text( - service.number, + operation.number, style: TextStyle( fontWeight: FontWeight.w600, color: context.primaryText, @@ -157,7 +157,7 @@ class _LatestServicesCardContent extends StatelessWidget { ), ), Text( - "${service.createdAt?.day}/${service.createdAt?.month}", + "${operation.createdAt?.day}/${operation.createdAt?.month}", style: TextStyle( color: context.secondaryText, fontSize: 12, diff --git a/lib/features/home/ui/home_screen.dart b/lib/features/home/ui/home_screen.dart index 91ab08c..69786ee 100644 --- a/lib/features/home/ui/home_screen.dart +++ b/lib/features/home/ui/home_screen.dart @@ -185,7 +185,7 @@ class HomeScreen extends StatelessWidget { color: Colors.blue, onTap: () { // Entriamo nel form! Nessun parametro extra = Nuovo Servizio - context.push('/service-form'); + context.push('/operation-form'); }, ), const SizedBox(width: 12), diff --git a/lib/features/onboarding/ui/store_onboarding_form.dart b/lib/features/onboarding/ui/store_onboarding_form.dart index 0f26732..26f5a6e 100644 --- a/lib/features/onboarding/ui/store_onboarding_form.dart +++ b/lib/features/onboarding/ui/store_onboarding_form.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; // <-- IMPORTANTE per i formatter +import 'package:flutter/operations.dart'; // <-- IMPORTANTE per i formatter import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/core/widgets/flux_text_field.dart'; import 'package:flux/features/master_data/store/models/store_model.dart'; diff --git a/lib/features/operations/blocs/services_cubit.dart b/lib/features/operations/blocs/operations_cubit.dart similarity index 100% rename from lib/features/operations/blocs/services_cubit.dart rename to lib/features/operations/blocs/operations_cubit.dart diff --git a/lib/features/operations/blocs/service_files_events.dart b/lib/features/operations/blocs/service_files_events.dart index 141d5ac..cb02eb2 100644 --- a/lib/features/operations/blocs/service_files_events.dart +++ b/lib/features/operations/blocs/service_files_events.dart @@ -17,11 +17,11 @@ class ServiceSavedEvent extends ServiceFilesEvent { class LoadServiceFilesEvent extends ServiceFilesEvent { final String? serviceId; - final ServiceModel? service; - const LoadServiceFilesEvent({this.serviceId, this.service}); + final ServiceModel? operation; + const LoadServiceFilesEvent({this.serviceId, this.operation}); @override - List get props => [serviceId, service]; + List get props => [serviceId, operation]; } class AddServiceFilesEvent extends ServiceFilesEvent { diff --git a/lib/features/operations/blocs/services_state.dart b/lib/features/operations/blocs/services_state.dart index 9d5a15a..5af7130 100644 --- a/lib/features/operations/blocs/services_state.dart +++ b/lib/features/operations/blocs/services_state.dart @@ -1,4 +1,4 @@ -part of 'services_cubit.dart'; +part of 'operations_cubit.dart'; enum ServicesStatus { initial, diff --git a/lib/features/operations/data/services_repository.dart b/lib/features/operations/data/services_repository.dart index ead6a04..f0f8233 100644 --- a/lib/features/operations/data/services_repository.dart +++ b/lib/features/operations/data/services_repository.dart @@ -18,7 +18,7 @@ class ServicesRepository { Future fetchServiceById(String id) async { try { final response = await _supabase - .from('service') + .from('operation') .select(''' *, customer(nome), @@ -47,7 +47,7 @@ class ServicesRepository { try { // Nota: 'customer(name, surname)' serve per il display name nella card var query = _supabase - .from('service') + .from('operation') .select(''' *, customer(nome), @@ -89,7 +89,7 @@ class ServicesRepository { required int limit, }) { return _supabase - .from('service') + .from('operation') .stream(primaryKey: ['id']) .eq('store_id', storeId) .order('created_at', ascending: false) @@ -101,12 +101,12 @@ class ServicesRepository { } // --- SALVATAGGIO COMPLETO (PRIMA PADRE, POI FIGLI) --- - Future saveFullService(ServiceModel service) async { + Future saveFullService(ServiceModel operation) async { try { // 1. Upsert del record principale final serviceData = await _supabase - .from('service') - .upsert(service.toMap()) + .from('operation') + .upsert(operation.toMap()) .select() .single(); @@ -114,7 +114,7 @@ class ServicesRepository { // 2. MODIFICA: Pulizia atomica dei figli // Se stiamo modificando (id != null), resettiamo le tabelle collegate - if (service.id != null) { + if (operation.id != null) { await Future.wait([ _supabase.from('energy_service').delete().eq('service_id', newId), _supabase.from('fin_service').delete().eq('service_id', newId), @@ -129,36 +129,36 @@ class ServicesRepository { // 3. Inserimento dei moduli in parallelo per velocità final List insertTasks = []; - if (service.energyServices.isNotEmpty) { + if (operation.energyServices.isNotEmpty) { insertTasks.add( _supabase .from('energy_service') .insert( - service.energyServices + operation.energyServices .map((item) => item.copyWith(serviceId: newId).toMap()) .toList(), ), ); } - if (service.finServices.isNotEmpty) { + if (operation.finServices.isNotEmpty) { insertTasks.add( _supabase .from('fin_service') .insert( - service.finServices + operation.finServices .map((item) => item.copyWith(serviceId: newId).toMap()) .toList(), ), ); } - if (service.entertainmentServices.isNotEmpty) { + if (operation.entertainmentServices.isNotEmpty) { insertTasks.add( _supabase .from('entertainment_service') .insert( - service.entertainmentServices + operation.entertainmentServices .map((item) => item.copyWith(serviceId: newId).toMap()) .toList(), ), @@ -171,7 +171,7 @@ class ServicesRepository { // 4. UPLOAD DEI FILE LOCALI (Nuovi) // Filtriamo solo i file che non hanno ancora un ID (quindi sono locali) - final localFilesToUpload = service.files + final localFilesToUpload = operation.files .where((f) => f.id == null) .toList(); @@ -180,7 +180,7 @@ class ServicesRepository { for (var file in localFilesToUpload) { final storagePath = - '$companyId/services/$newId/${DateTime.now().millisecondsSinceEpoch}_${file.name}.${file.extension}'; + '$companyId/operations/$newId/${DateTime.now().millisecondsSinceEpoch}_${file.name}.${file.extension}'; final String mimeType = file.extension.toLowerCase() == 'pdf' ? 'application/pdf' : 'image/${file.extension}'; @@ -216,7 +216,7 @@ class ServicesRepository { // Interroghiamo Supabase per farci restituire la pratica con TUTTI gli ID generati // (inclusi quelli della tabella service_file appena inseriti) final updatedServiceData = await _supabase - .from('service') + .from('operation') .select(''' *, energy_service(*), @@ -237,7 +237,7 @@ class ServicesRepository { // --- ELIMINAZIONE --- Future deleteService(String id) async { try { - await _supabase.from('service').delete().eq('id', id); + await _supabase.from('operation').delete().eq('id', id); } catch (e) { throw Exception('Errore durante l\'eliminazione: $e'); } @@ -247,11 +247,11 @@ class ServicesRepository { Future> fetchTopEntertainmentTypes(String companyId) async { try { // Cerchiamo i tipi più frequenti associati ai servizi di questa company - // Nota: dobbiamo passare attraverso la tabella 'service' per filtrare per company_id + // Nota: dobbiamo passare attraverso la tabella 'operation' per filtrare per company_id final response = await _supabase .from('entertainment_service') - .select('type, service!inner(store!inner(company_id))') - .eq('service.store.company_id', companyId) + .select('type, operation!inner(store!inner(company_id))') + .eq('operation.store.company_id', companyId) .limit(100); // Prendiamo un campione // Logica rapida per contare le occorrenze e prendere i primi 5 @@ -297,7 +297,7 @@ class ServicesRepository { '_', ); final storagePath = - '$companyId/services/$serviceId/${DateTime.now().millisecondsSinceEpoch}_$cleanFileName'; + '$companyId/operations/$serviceId/${DateTime.now().millisecondsSinceEpoch}_$cleanFileName'; final int fileSize = pickedFile.size; final fileToSave = ServiceFileModel( serviceId: serviceId, diff --git a/lib/features/operations/ui/service_form_screen/attachment_section.dart b/lib/features/operations/ui/service_form_screen/attachment_section.dart index 2211186..1a5e960 100644 --- a/lib/features/operations/ui/service_form_screen/attachment_section.dart +++ b/lib/features/operations/ui/service_form_screen/attachment_section.dart @@ -6,7 +6,7 @@ import 'package:flux/core/widgets/image_viewer_widget.dart'; import 'package:flux/core/widgets/pdf_viewer_widget.dart'; import 'package:flux/core/widgets/qr_upload_dialog.dart'; import 'package:flux/features/operations/blocs/service_files_bloc.dart'; -import 'package:flux/features/operations/blocs/services_cubit.dart'; +import 'package:flux/features/operations/blocs/operations_cubit.dart'; import 'package:flux/features/operations/models/service_file_model.dart'; class AttachmentsSection extends StatelessWidget { @@ -310,7 +310,7 @@ class AttachmentsSection extends StatelessWidget { }, child: QrUploadDialog( deepLinkUrl: - 'fluxapp:///service/${currentService!.id}/upload?name=${Uri.encodeComponent(nomePratica)}', + 'fluxapp:///operation/${currentService!.id}/upload?name=${Uri.encodeComponent(nomePratica)}', title: 'Scatta per\n$nomePratica', ), ), diff --git a/lib/features/operations/ui/service_form_screen/customer_section.dart b/lib/features/operations/ui/service_form_screen/customer_section.dart index 3a5c42c..bb0a7e8 100644 --- a/lib/features/operations/ui/service_form_screen/customer_section.dart +++ b/lib/features/operations/ui/service_form_screen/customer_section.dart @@ -3,9 +3,9 @@ import 'package:flux/features/customers/ui/customer_search_sheet.dart'; import 'package:flux/features/operations/models/service_model.dart'; class CustomerSection extends StatelessWidget { - final ServiceModel service; + final ServiceModel operation; - const CustomerSection({super.key, required this.service}); + const CustomerSection({super.key, required this.operation}); void _openCustomerSearch(BuildContext context) { showModalBottomSheet( @@ -28,8 +28,8 @@ class CustomerSection extends StatelessWidget { @override Widget build(BuildContext context) { - // Niente BlocBuilder qui! Leggiamo solo la variabile 'service' - final hasCustomer = service.customerId != null; + // Niente BlocBuilder qui! Leggiamo solo la variabile 'operation' + final hasCustomer = operation.customerId != null; return Card( elevation: 2, @@ -74,7 +74,7 @@ class CustomerSection extends StatelessWidget { children: [ Expanded( child: Text( - service.customerDisplayName ?? "Cliente Selezionato", + operation.customerDisplayName ?? "Cliente Selezionato", style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, diff --git a/lib/features/operations/ui/service_form_screen/energy_service_dialog.dart b/lib/features/operations/ui/service_form_screen/energy_service_dialog.dart index 67bd0b4..04c0ef4 100644 --- a/lib/features/operations/ui/service_form_screen/energy_service_dialog.dart +++ b/lib/features/operations/ui/service_form_screen/energy_service_dialog.dart @@ -63,7 +63,7 @@ class _EnergyServiceDialogState extends State { }, ) : _EnergyList( - services: _tempList, + operations: _tempList, onDelete: (index) { setState(() => _tempList.removeAt(index)); }, @@ -101,14 +101,14 @@ class _EnergyServiceDialogState extends State { // VISTA 1: LA LISTA DEI CONTRATTI // ========================================== class _EnergyList extends StatelessWidget { - final List services; + final List operations; final List activeProviders; // <--- NUOVO: La lista vera dal Cubit final Function(int) onDelete; final VoidCallback onAddTap; const _EnergyList({ - required this.services, + required this.operations, required this.activeProviders, // <--- Richiesto required this.onDelete, required this.onAddTap, @@ -120,7 +120,7 @@ class _EnergyList extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - if (services.isEmpty) + if (operations.isEmpty) const Padding( padding: EdgeInsets.symmetric(vertical: 32.0), child: Text( @@ -133,10 +133,10 @@ class _EnergyList extends StatelessWidget { Flexible( child: ListView.separated( shrinkWrap: true, - itemCount: services.length, + itemCount: operations.length, separatorBuilder: (_, _) => const Divider(height: 1), itemBuilder: (context, index) { - final s = services[index]; + final s = operations[index]; final isLuce = s.type == EnergyType.luce; // LA MAGIA: Troviamo il nome partendo dall'ID salvato nel servizio diff --git a/lib/features/operations/ui/service_form_screen/entertainment_service_card.dart b/lib/features/operations/ui/service_form_screen/entertainment_service_card.dart index e1899f9..d7d08a5 100644 --- a/lib/features/operations/ui/service_form_screen/entertainment_service_card.dart +++ b/lib/features/operations/ui/service_form_screen/entertainment_service_card.dart @@ -67,7 +67,7 @@ class _EntertainmentServiceDialogState builder: (context, state) { // Passiamo allProviders per garantire la visione dello storico return _EntertainmentList( - services: _tempList, + operations: _tempList, allProviders: state.allProviders, onDelete: (index) => setState(() => _tempList.removeAt(index)), @@ -94,13 +94,13 @@ class _EntertainmentServiceDialogState } class _EntertainmentList extends StatelessWidget { - final List services; + final List operations; final List allProviders; final Function(int) onDelete; final VoidCallback onAddTap; const _EntertainmentList({ - required this.services, + required this.operations, required this.allProviders, required this.onDelete, required this.onAddTap, @@ -112,7 +112,7 @@ class _EntertainmentList extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - if (services.isEmpty) + if (operations.isEmpty) const Padding( padding: EdgeInsets.symmetric(vertical: 32.0), child: Text( @@ -125,10 +125,10 @@ class _EntertainmentList extends StatelessWidget { Flexible( child: ListView.separated( shrinkWrap: true, - itemCount: services.length, + itemCount: operations.length, separatorBuilder: (_, _) => const Divider(height: 1), itemBuilder: (context, index) { - final s = services[index]; + final s = operations[index]; final providerName = allProviders .firstWhere( diff --git a/lib/features/operations/ui/service_form_screen/finance_service_dialog.dart b/lib/features/operations/ui/service_form_screen/finance_service_dialog.dart index 0b0248d..a8196c9 100644 --- a/lib/features/operations/ui/service_form_screen/finance_service_dialog.dart +++ b/lib/features/operations/ui/service_form_screen/finance_service_dialog.dart @@ -74,7 +74,7 @@ class _FinanceServiceDialogState extends State { return BlocBuilder( builder: (context, prodState) { return _FinanceList( - services: _tempList, + operations: _tempList, allProviders: provState.allProviders, // Per vedere lo storico allModels: prodState.models, @@ -109,14 +109,14 @@ class _FinanceServiceDialogState extends State { // VISTA LISTA (STORICA) // =========================================================================== class _FinanceList extends StatelessWidget { - final List services; + final List operations; final List allProviders; final List allModels; final Function(int) onDelete; final VoidCallback onAddTap; const _FinanceList({ - required this.services, + required this.operations, required this.allProviders, required this.allModels, required this.onDelete, @@ -125,7 +125,7 @@ class _FinanceList extends StatelessWidget { @override Widget build(BuildContext context) { - if (services.isEmpty) { + if (operations.isEmpty) { return Column( mainAxisSize: MainAxisSize.min, children: [ @@ -151,10 +151,10 @@ class _FinanceList extends StatelessWidget { Flexible( child: ListView.separated( shrinkWrap: true, - itemCount: services.length, + itemCount: operations.length, separatorBuilder: (_, _) => const Divider(), itemBuilder: (context, index) { - final s = services[index]; + final s = operations[index]; // Cerchiamo il nome del provider in TUTTI quelli caricati (storico) final providerName = allProviders diff --git a/lib/features/operations/ui/service_form_screen/general_info_section.dart b/lib/features/operations/ui/service_form_screen/general_info_section.dart index cf1c3ca..f679b9f 100644 --- a/lib/features/operations/ui/service_form_screen/general_info_section.dart +++ b/lib/features/operations/ui/service_form_screen/general_info_section.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flux/features/operations/blocs/services_cubit.dart'; +import 'package:flux/features/operations/blocs/operations_cubit.dart'; import 'package:flux/features/operations/models/service_model.dart'; class GeneralInfoSection extends StatelessWidget { - final ServiceModel service; - const GeneralInfoSection({super.key, required this.service}); + final ServiceModel operation; + const GeneralInfoSection({super.key, required this.operation}); @override Widget build(BuildContext context) { @@ -34,7 +34,7 @@ class GeneralInfoSection extends StatelessWidget { // Numero di Riferimento / Telefono TextFormField( - initialValue: service.number, + initialValue: operation.number, keyboardType: TextInputType .phone, // Fa aprire il tastierino numerico su mobile decoration: const InputDecoration( @@ -59,7 +59,7 @@ class GeneralInfoSection extends StatelessWidget { "Pratica in lavorazione", style: TextStyle(fontSize: 12), ), - value: service.isBozza, + value: operation.isBozza, activeThumbColor: Colors.orange, contentPadding: EdgeInsets.zero, onChanged: (val) { @@ -75,7 +75,7 @@ class GeneralInfoSection extends StatelessWidget { "Esito positivo", style: TextStyle(fontSize: 12), ), - value: service.resultOk, + value: operation.resultOk, activeThumbColor: Colors.green, contentPadding: EdgeInsets.zero, onChanged: (val) { @@ -89,7 +89,7 @@ class GeneralInfoSection extends StatelessWidget { // Campo Note TextFormField( - initialValue: service.note, + initialValue: operation.note, maxLines: 4, minLines: 2, decoration: const InputDecoration( diff --git a/lib/features/operations/ui/service_form_screen/service_form_screen.dart b/lib/features/operations/ui/service_form_screen/service_form_screen.dart index 4022f10..400dc41 100644 --- a/lib/features/operations/ui/service_form_screen/service_form_screen.dart +++ b/lib/features/operations/ui/service_form_screen/service_form_screen.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flux/features/operations/blocs/services_cubit.dart'; +import 'package:flux/features/operations/blocs/operations_cubit.dart'; import 'package:flux/features/operations/models/service_model.dart'; import 'package:flux/features/operations/ui/service_form_screen/attachment_section.dart'; import 'package:flux/features/operations/ui/service_form_screen/customer_section.dart'; @@ -70,7 +70,7 @@ class _ServiceFormScreenState extends State { } }, builder: (context, state) { - final service = state.currentService; + final operation = state.currentService; final isSaving = state.status == ServicesStatus.saving; final isEditMode = widget.serviceId != null; @@ -89,7 +89,7 @@ class _ServiceFormScreenState extends State { ), ), ) - else if (service != null) ...[ + else if (operation != null) ...[ IconButton( icon: const Icon(Icons.edit_note), tooltip: "Salva come Bozza", @@ -107,20 +107,20 @@ class _ServiceFormScreenState extends State { ], ], ), - body: (service == null) + body: (operation == null) ? const Center(child: CircularProgressIndicator()) : SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - CustomerSection(service: service), + CustomerSection(operation: operation), const SizedBox(height: 24), - GeneralInfoSection(service: service), + GeneralInfoSection(operation: operation), const SizedBox(height: 24), - ServicesGrid(service: service), + ServicesGrid(operation: operation), const SizedBox(height: 32), AttachmentsSection(), diff --git a/lib/features/operations/ui/service_form_screen/services_grid.dart b/lib/features/operations/ui/service_form_screen/services_grid.dart index f9d5874..bc0ab95 100644 --- a/lib/features/operations/ui/service_form_screen/services_grid.dart +++ b/lib/features/operations/ui/service_form_screen/services_grid.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/features/master_data/products/blocs/product_cubit.dart'; -import 'package:flux/features/operations/blocs/services_cubit.dart'; +import 'package:flux/features/operations/blocs/operations_cubit.dart'; import 'package:flux/features/operations/models/energy_service_model.dart'; import 'package:flux/features/operations/models/entertainment_service_model.dart'; import 'package:flux/features/operations/models/fin_service_model.dart'; @@ -13,9 +13,9 @@ import 'package:flux/features/operations/ui/service_form_screen/finance_service_ import 'package:flux/features/operations/ui/service_form_screen/int_dialogs.dart'; // Assicurati di importare il modello class ServicesGrid extends StatelessWidget { - final ServiceModel service; + final ServiceModel operation; - const ServicesGrid({super.key, required this.service}); + const ServicesGrid({super.key, required this.operation}); @override Widget build(BuildContext context) { @@ -52,65 +52,65 @@ class ServicesGrid extends StatelessWidget { // --- CONTATORI SEMPLICI --- ActionCard( label: "AL", - count: service.al, + count: operation.al, icon: Icons.sim_card, color: Colors.blue, onTap: () => updateCountDialog( context, "AL", - service.al, + operation.al, (val) => context.read().updateField(al: val), ), ), ActionCard( label: "MNP", - count: service.mnp, + count: operation.mnp, icon: Icons.phone_android, color: Colors.indigo, onTap: () => updateCountDialog( context, "MNP", - service.mnp, + operation.mnp, (val) => context.read().updateField(mnp: val), ), ), ActionCard( label: "NIP", - count: service.nip, + count: operation.nip, icon: Icons.compare_arrows, color: Colors.cyan, onTap: () => updateCountDialog( context, "NIP", - service.nip, + operation.nip, (val) => context.read().updateField(nip: val), ), ), ActionCard( label: "Unica", - count: service.unica, + count: operation.unica, icon: Icons.all_inclusive, color: Colors.purple, onTap: () => updateCountDialog( context, "Unica", - service.unica, + operation.unica, (val) => context.read().updateField(unica: val), ), ), ActionCard( label: "Telepass", - count: service.telepass, + count: operation.telepass, icon: Icons.directions_car, color: Colors.amber.shade700, onTap: () => updateCountDialog( context, "Telepass", - service.telepass, + operation.telepass, (val) => context.read().updateField( telepass: val, ), @@ -120,7 +120,7 @@ class ServicesGrid extends StatelessWidget { // --- MODULI COMPLESSI (Le liste) --- ActionCard( label: "Energia", - count: service.energyServices.length, + count: operation.energyServices.length, icon: Icons.bolt, color: Colors.green, onTap: () async { @@ -128,8 +128,8 @@ class ServicesGrid extends StatelessWidget { final result = await showDialog>( context: context, builder: (context) => EnergyServiceDialog( - currentStoreId: service.storeId, - initialServices: service + currentStoreId: operation.storeId, + initialServices: operation .energyServices, // Passiamo la lista attuale ), ); @@ -144,7 +144,7 @@ class ServicesGrid extends StatelessWidget { ), ActionCard( label: "Finanziam.", - count: service.finServices.length, + count: operation.finServices.length, icon: Icons.euro_symbol, color: Colors.teal, onTap: () async { @@ -152,9 +152,9 @@ class ServicesGrid extends StatelessWidget { context: context, builder: (context) => FinanceServiceDialog( productCubit: context.read(), - currentStoreId: service.storeId, - initialServices: - service.finServices, // Passiamo la lista attuale + currentStoreId: operation.storeId, + initialServices: operation + .finServices, // Passiamo la lista attuale ), ); @@ -165,7 +165,7 @@ class ServicesGrid extends StatelessWidget { ), ActionCard( label: "Intratten.", - count: service.entertainmentServices.length, + count: operation.entertainmentServices.length, icon: Icons.movie_filter_outlined, color: Colors.purple, onTap: () async { @@ -173,8 +173,8 @@ class ServicesGrid extends StatelessWidget { await showDialog>( context: context, builder: (context) => EntertainmentServiceDialog( - initialServices: service.entertainmentServices, - currentStoreId: service.storeId, + initialServices: operation.entertainmentServices, + currentStoreId: operation.storeId, ), ); diff --git a/lib/features/operations/ui/services_screen.dart b/lib/features/operations/ui/services_screen.dart index 2c1ec32..4935529 100644 --- a/lib/features/operations/ui/services_screen.dart +++ b/lib/features/operations/ui/services_screen.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flux/features/operations/blocs/services_cubit.dart'; +import 'package:flux/features/operations/blocs/operations_cubit.dart'; import 'package:flux/features/operations/models/service_model.dart'; import 'package:flux/features/operations/utils/service_actions.dart'; import 'package:go_router/go_router.dart'; @@ -107,8 +107,8 @@ class _ServicesScreenState extends State { ); } - final service = state.allServices[index]; - return _buildServiceCard(context, service); + final operation = state.allServices[index]; + return _buildServiceCard(context, operation); }, ), ); @@ -121,7 +121,7 @@ class _ServicesScreenState extends State { ); } - Widget _buildServiceCard(BuildContext context, ServiceModel service) { + Widget _buildServiceCard(BuildContext context, ServiceModel operation) { return Card( margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), elevation: 2, @@ -132,14 +132,14 @@ class _ServicesScreenState extends State { children: [ Expanded( child: Text( - service.customerDisplayName ?? "Cliente sconosciuto", + operation.customerDisplayName ?? "Cliente sconosciuto", style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), ), ), - if (service.isBozza) + if (operation.isBozza) const Chip( label: Text( "BOZZA", @@ -155,20 +155,20 @@ class _ServicesScreenState extends State { children: [ const SizedBox(height: 4), Text( - "Pratica: ${service.number} • ${service.createdAt?.day}/${service.createdAt?.month}/${service.createdAt?.year}", + "Pratica: ${operation.number} • ${operation.createdAt?.day}/${operation.createdAt?.month}/${operation.createdAt?.year}", ), const SizedBox(height: 8), // I nostri mini-chip per i servizi attivati Wrap( spacing: 6, children: [ - if (service.al > 0 || service.mnp > 0) + if (operation.al > 0 || operation.mnp > 0) _miniBadge("📞 Tel", Colors.blue), - if (service.energyServices.isNotEmpty) + if (operation.energyServices.isNotEmpty) _miniBadge("⚡ Energy", Colors.green), - if (service.finServices.isNotEmpty) + if (operation.finServices.isNotEmpty) _miniBadge("💰 Fin", Colors.purple), - if (service.entertainmentServices.isNotEmpty) + if (operation.entertainmentServices.isNotEmpty) _miniBadge("📺 Ent", Colors.red), ], ), @@ -176,10 +176,12 @@ class _ServicesScreenState extends State { ), trailing: const Icon(Icons.chevron_right), onTap: () => context.pushNamed( - 'service-form', - extra: service, // <-- LA MAGIA È QUI: Passa l'oggetto intero! + 'operation-form', + extra: operation, // <-- LA MAGIA È QUI: Passa l'oggetto intero! // Teniamo anche il parametro URL per coerenza di routing - queryParameters: service.id != null ? {'serviceId': service.id!} : {}, + queryParameters: operation.id != null + ? {'serviceId': operation.id!} + : {}, ), ), ); diff --git a/lib/features/operations/utils/service_actions.dart b/lib/features/operations/utils/service_actions.dart index ca8565f..c0bdf38 100644 --- a/lib/features/operations/utils/service_actions.dart +++ b/lib/features/operations/utils/service_actions.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/core/blocs/session/session_cubit.dart'; import 'package:flux/features/master_data/store/bloc/store_cubit.dart'; -import 'package:flux/features/operations/blocs/services_cubit.dart'; +import 'package:flux/features/operations/blocs/operations_cubit.dart'; import 'package:flux/features/operations/models/service_model.dart'; import 'package:go_router/go_router.dart'; @@ -67,7 +67,7 @@ void startNewService(BuildContext context) { Navigator.pop(modalContext); // 3. Naviga verso il form - context.pushNamed('service-form'); + context.pushNamed('operation-form'); }, ), ), diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 84c90f5..a0fe5df 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -1,13 +1,13 @@ { "@@locale": "en", "welcomeBack": "Welcome back, {name}! 👋", - "latestServices": "Latest Services", + "latestServices": "Latest Operations", "masterData": "Master Data", "settings": "Settings", - "newService": "Service", + "newService": "Operation", "expiring_contracts": "Expiring Contracts", "sticky_notes": "Sticky Notes", "my_tasks": "My Tasks", - "latest_service_tickets": "Latest service tickets" + "latest_service_tickets": "Latest operation tickets" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 532039d..a6515df 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -26,7 +26,7 @@ import 'package:flux/features/master_data/staff/blocs/staff_cubit.dart'; import 'package:flux/features/master_data/staff/data/staff_repository.dart'; import 'package:flux/features/master_data/store/bloc/store_cubit.dart'; import 'package:flux/features/master_data/store/data/store_repository.dart'; -import 'package:flux/features/operations/blocs/services_cubit.dart'; +import 'package:flux/features/operations/blocs/operations_cubit.dart'; import 'package:flux/features/operations/data/services_repository.dart'; import 'package:flux/features/settings/settings.dart'; diff --git a/macos/Runner/Base.lproj/MainMenu.xib b/macos/Runner/Base.lproj/MainMenu.xib index 80e867a..02538c9 100644 --- a/macos/Runner/Base.lproj/MainMenu.xib +++ b/macos/Runner/Base.lproj/MainMenu.xib @@ -35,9 +35,9 @@ - + - +