diff --git a/lib/features/master_data/products/blocs/product_cubit.dart b/lib/features/master_data/products/blocs/product_cubit.dart index d469b75..312be0a 100644 --- a/lib/features/master_data/products/blocs/product_cubit.dart +++ b/lib/features/master_data/products/blocs/product_cubit.dart @@ -10,9 +10,9 @@ part 'product_state.dart'; class ProductCubit extends Cubit { final ProductRepository _repository = GetIt.I(); - final SessionBloc _sessionBloc; + final SessionBloc _sessionBloc = GetIt.I(); - ProductCubit(this._sessionBloc) : super(const ProductState()); + ProductCubit() : super(const ProductState()); // Caricamento iniziale dei Brand Future loadBrands() async { diff --git a/lib/features/master_data/providers/blocs/provider_cubit.dart b/lib/features/master_data/providers/blocs/provider_cubit.dart index c78e65c..0a7ee5b 100644 --- a/lib/features/master_data/providers/blocs/provider_cubit.dart +++ b/lib/features/master_data/providers/blocs/provider_cubit.dart @@ -52,9 +52,9 @@ class ProvidersState extends Equatable { class ProvidersCubit extends Cubit { final ProviderRepository _repository = GetIt.I(); - final SessionBloc _sessionBloc; + final SessionBloc _sessionBloc = GetIt.I(); - ProvidersCubit(this._sessionBloc) : super(const ProvidersState()); + ProvidersCubit() : super(const ProvidersState()); // Carica i provider della company e quelli associati a uno store specifico Future loadProviders(StoreModel? store) async { diff --git a/lib/features/master_data/staff/blocs/staff_cubit.dart b/lib/features/master_data/staff/blocs/staff_cubit.dart index c1bff15..64a14b9 100644 --- a/lib/features/master_data/staff/blocs/staff_cubit.dart +++ b/lib/features/master_data/staff/blocs/staff_cubit.dart @@ -10,9 +10,9 @@ part 'staff_state.dart'; class StaffCubit extends Cubit { final StaffRepository _repository = GetIt.I.get(); - final SessionBloc _sessionBloc; + final SessionBloc _sessionBloc = GetIt.I(); - StaffCubit(this._sessionBloc) : super(const StaffState()); + StaffCubit() : super(const StaffState()); // Carica tutto lo staff della compagnia Future loadAllStaff() async { diff --git a/lib/features/master_data/store/bloc/store_cubit.dart b/lib/features/master_data/store/bloc/store_cubit.dart index b36c87c..8d34f5d 100644 --- a/lib/features/master_data/store/bloc/store_cubit.dart +++ b/lib/features/master_data/store/bloc/store_cubit.dart @@ -13,9 +13,9 @@ part 'store_state.dart'; class StoreCubit extends Cubit { final StoreRepository _repository = GetIt.I(); final StaffRepository _staffRepository = GetIt.I(); - final SessionBloc _sessionBloc; + final SessionBloc _sessionBloc = GetIt.I(); - StoreCubit(this._sessionBloc) : super(const StoreState(stores: [])); + StoreCubit() : super(const StoreState(stores: [])); Future createStore(final StoreModel store) async { emit(state.copyWith(status: StoreStatus.loading)); diff --git a/lib/features/products/blocs/product_cubit.dart b/lib/features/products/blocs/product_cubit.dart deleted file mode 100644 index e566657..0000000 --- a/lib/features/products/blocs/product_cubit.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'package:equatable/equatable.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flux/core/blocs/session/session_bloc.dart'; -import 'package:flux/features/products/data/product_repository.dart'; -import 'package:flux/features/products/models/brand_model.dart'; -import 'package:flux/features/products/models/model_model.dart'; -import 'package:get_it/get_it.dart'; - -part 'product_state.dart'; - -class ProductCubit extends Cubit { - final ProductRepository _repository = GetIt.I(); - final SessionBloc _sessionBloc; - - ProductCubit(this._sessionBloc) : super(const ProductState()); - - // Caricamento iniziale dei Brand - Future loadBrands() async { - emit(state.copyWith(status: ProductStatus.loading)); - try { - final brands = await _repository.getBrands( - _sessionBloc.state.company!.id, - ); - emit(state.copyWith(status: ProductStatus.success, brands: brands)); - } catch (e) { - emit( - state.copyWith(status: ProductStatus.error, errorMessage: e.toString()), - ); - } - } - - // Selezione Brand e caricamento Modelli - Future selectBrand(BrandModel? brand) async { - if (brand == null) { - emit(state.copyWith(selectedBrand: null, models: [])); - return; - } - - emit(state.copyWith(status: ProductStatus.loading, selectedBrand: brand)); - try { - final models = await _repository.getModelsByBrand(brand.id!); - emit(state.copyWith(status: ProductStatus.success, models: models)); - } catch (e) { - emit( - state.copyWith(status: ProductStatus.error, errorMessage: e.toString()), - ); - } - } - - // Aggiungi/Modifica Brand - Future saveBrand(String name, {String? id}) async { - try { - final brand = BrandModel( - id: id, - name: name, - companyId: _sessionBloc.state.company!.id, - ); - final newBrand = await _repository.upsertBrand(brand); - await loadBrands(); // Ricarichiamo la lista aggiornata - selectBrand(newBrand); - } catch (e) { - emit( - state.copyWith(status: ProductStatus.error, errorMessage: e.toString()), - ); - } - } - - // Aggiungi/Modifica Modello - Future saveModel(String name, {String? id}) async { - if (state.selectedBrand == null) return; - - try { - final model = ModelModel( - id: id, - name: name, - brandId: state.selectedBrand!.id!, - nameWithBrand: '', // Gestito dal trigger SQL - ); - await _repository.upsertModel(model); - await selectBrand( - state.selectedBrand, - ); // Ricarichiamo i modelli del brand - } catch (e) { - emit( - state.copyWith(status: ProductStatus.error, errorMessage: e.toString()), - ); - } - } - - // Disattivazione (Soft Delete) - Future toggleStatus(String table, String id, bool currentStatus) async { - try { - await _repository.toggleActiveStatus(table, id, !currentStatus); - if (table == 'brand') { - await loadBrands(); - } else { - await selectBrand(state.selectedBrand); - } - } catch (e) { - emit( - state.copyWith(status: ProductStatus.error, errorMessage: e.toString()), - ); - } - } -} diff --git a/lib/features/products/blocs/product_state.dart b/lib/features/products/blocs/product_state.dart deleted file mode 100644 index 8d5ab94..0000000 --- a/lib/features/products/blocs/product_state.dart +++ /dev/null @@ -1,44 +0,0 @@ -part of 'product_cubit.dart'; - -enum ProductStatus { initial, loading, success, error } - -class ProductState extends Equatable { - final ProductStatus status; - final List brands; - final List models; - final BrandModel? selectedBrand; // Il brand attualmente selezionato - final String? errorMessage; - - const ProductState({ - this.status = ProductStatus.initial, - this.brands = const [], - this.models = const [], - this.selectedBrand, - this.errorMessage, - }); - - ProductState copyWith({ - ProductStatus? status, - List? brands, - List? models, - BrandModel? selectedBrand, - String? errorMessage, - }) { - return ProductState( - status: status ?? this.status, - brands: brands ?? this.brands, - models: models ?? this.models, - selectedBrand: selectedBrand ?? this.selectedBrand, - errorMessage: errorMessage ?? this.errorMessage, - ); - } - - @override - List get props => [ - status, - brands, - models, - selectedBrand, - errorMessage, - ]; -} diff --git a/lib/features/products/data/product_repository.dart b/lib/features/products/data/product_repository.dart deleted file mode 100644 index 874854f..0000000 --- a/lib/features/products/data/product_repository.dart +++ /dev/null @@ -1,86 +0,0 @@ -import 'package:get_it/get_it.dart'; -import 'package:supabase_flutter/supabase_flutter.dart'; -import '../models/brand_model.dart'; -import '../models/model_model.dart'; - -class ProductRepository { - final SupabaseClient _client = GetIt.I(); - - // --- BRAND --- - - /// Recupera tutti i brand dell'azienda - Future> getBrands(String companyId) async { - try { - final response = await _client - .from('brand') - .select() - .eq('company_id', companyId) - .eq('is_active', true) - .order('name'); - - return (response as List).map((b) => BrandModel.fromJson(b)).toList(); - } catch (e) { - throw 'Errore nel recupero dei Brand'; - } - } - - /// Crea o aggiorna un brand - Future upsertBrand(BrandModel brand) async { - try { - final response = await _client - .from('brand') - .upsert(brand.toJson()) - .select() - .single(); - - return BrandModel.fromJson(response); - } catch (e) { - throw 'Errore nel salvataggio del Brand'; - } - } - - // --- MODEL --- - - /// Recupera i modelli di un brand specifico - Future> getModelsByBrand(String brandId) async { - try { - final response = await _client - .from('model') - .select() - .eq('brand_id', brandId) - .eq('is_active', true) - .order('name'); - - return (response as List).map((m) => ModelModel.fromJson(m)).toList(); - } catch (e) { - throw 'Errore nel recupero dei modelli'; - } - } - - /// Crea o aggiorna un modello - /// NOTA: name_with_brand verrĂ  gestito dal trigger SQL che hai lanciato! - Future upsertModel(ModelModel model) async { - try { - final response = await _client - .from('model') - .upsert(model.toJson()) - .select() - .single(); - - return ModelModel.fromJson(response); - } catch (e) { - throw 'Errore nel salvataggio del modello'; - } - } - - // --- DELETE (LOGICA) --- - - /// Disattiva un brand o un modello (Soft Delete per non rompere le FK delle operazioni passate) - Future toggleActiveStatus(String table, String id, bool status) async { - try { - await _client.from(table).update({'is_active': status}).eq('id', id); - } catch (e) { - throw 'Errore durante la modifica dello stato'; - } - } -} diff --git a/lib/features/products/models/brand_model.dart b/lib/features/products/models/brand_model.dart deleted file mode 100644 index 72e02b1..0000000 --- a/lib/features/products/models/brand_model.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'package:equatable/equatable.dart'; -import 'package:flux/core/utils/string_extensions.dart'; - -class BrandModel extends Equatable { - final String? id; - final String name; - final String companyId; - final bool isActive; - final DateTime? createdAt; - - const BrandModel({ - this.id, - required this.name, - required this.companyId, - this.isActive = true, - this.createdAt, - }); - - factory BrandModel.fromJson(Map json) { - return BrandModel( - id: json['id'] as String, - name: (json['name'] as String).myFormat(), - companyId: json['company_id'] as String, - isActive: json['is_active'] as bool? ?? true, - createdAt: json['created_at'] != null - ? DateTime.parse(json['created_at']) - : null, - ); - } - - Map toJson() { - return { - if (id != null) 'id': id, - 'name': name.toLowerCase().trim(), - 'company_id': companyId, - 'is_active': isActive, - }; - } - - BrandModel copyWith({ - String? id, - String? name, - String? companyId, - bool? isActive, - DateTime? createdAt, - }) { - return BrandModel( - id: id ?? this.id, - name: name ?? this.name, - companyId: companyId ?? this.companyId, - isActive: isActive ?? this.isActive, - createdAt: createdAt ?? this.createdAt, - ); - } - - @override - List get props => [id, name, companyId, isActive, createdAt]; -} diff --git a/lib/features/products/models/model_model.dart b/lib/features/products/models/model_model.dart deleted file mode 100644 index 31aa504..0000000 --- a/lib/features/products/models/model_model.dart +++ /dev/null @@ -1,70 +0,0 @@ -import 'package:equatable/equatable.dart'; -import 'package:flux/core/utils/string_extensions.dart'; - -class ModelModel extends Equatable { - final String? id; - final String name; - final String nameWithBrand; - final String brandId; - final bool isActive; - final DateTime? createdAt; - - const ModelModel({ - this.id, - required this.name, - required this.nameWithBrand, - required this.brandId, - this.isActive = true, - this.createdAt, - }); - - factory ModelModel.fromJson(Map json) { - return ModelModel( - id: json['id'] as String, - name: (json['name'] as String).myFormat(), - nameWithBrand: (json['name_with_brand'] as String).myFormat(), - brandId: json['brand_id'] as String, - isActive: json['is_active'] as bool? ?? true, - createdAt: json['created_at'] != null - ? DateTime.parse(json['created_at']) - : null, - ); - } - - Map toJson() { - return { - if (id != null) 'id': id, - 'name': name.toLowerCase().trim(), - 'brand_id': brandId, - 'is_active': isActive, - }; - } - - ModelModel copyWith({ - String? id, - String? name, - String? nameWithBrand, - String? brandId, - bool? isActive, - DateTime? createdAt, - }) { - return ModelModel( - id: id ?? this.id, - name: name ?? this.name, - nameWithBrand: nameWithBrand ?? this.nameWithBrand, - brandId: brandId ?? this.brandId, - isActive: isActive ?? this.isActive, - createdAt: createdAt ?? this.createdAt, - ); - } - - @override - List get props => [ - id, - name, - nameWithBrand, - brandId, - isActive, - createdAt, - ]; -} diff --git a/lib/features/products/ui/brand_selector.dart b/lib/features/products/ui/brand_selector.dart deleted file mode 100644 index 5743587..0000000 --- a/lib/features/products/ui/brand_selector.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flux/core/theme/theme.dart'; -import 'package:flux/features/products/blocs/product_cubit.dart'; -import 'package:flux/features/products/models/brand_model.dart'; -import 'package:flux/features/products/ui/product_dialogs.dart'; -import 'package:flux/features/products/ui/round_action_button.dart'; - -class BrandSelector extends StatelessWidget { - final ProductState state; - const BrandSelector(this.state, {super.key}); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: context.background, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: context.accent.withValues(alpha: 0.1)), - ), - child: Row( - children: [ - Expanded( - child: DropdownButtonFormField( - initialValue: state.selectedBrand, - //value: state.selectedBrand, - decoration: const InputDecoration( - labelText: "Seleziona Brand", - prefixIcon: Icon(Icons.branding_watermark_outlined), - ), - items: state.brands.map((brand) { - return DropdownMenuItem(value: brand, child: Text(brand.name)); - }).toList(), - onChanged: (brand) => - context.read().selectBrand(brand), - ), - ), - const SizedBox(width: 16), - // Pulsanti rapidi Brand - RoundActionButton( - icon: Icons.add, - onTap: () => showBrandDialog(context), - tooltip: "Nuovo Brand", - ), - if (state.selectedBrand != null) ...[ - const SizedBox(width: 8), - RoundActionButton( - icon: Icons.edit_outlined, - onTap: () => showBrandDialog(context, brand: state.selectedBrand), - tooltip: "Modifica Brand", - ), - ], - ], - ), - ); - } -} diff --git a/lib/features/products/ui/models_list.dart b/lib/features/products/ui/models_list.dart deleted file mode 100644 index d398986..0000000 --- a/lib/features/products/ui/models_list.dart +++ /dev/null @@ -1,79 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flux/core/theme/theme.dart'; -import 'package:flux/features/products/blocs/product_cubit.dart'; -import 'package:flux/features/products/ui/product_dialogs.dart'; - -class ModelsList extends StatelessWidget { - final ProductState state; - const ModelsList(this.state, {super.key}); - - @override - Widget build(BuildContext context) { - if (state.selectedBrand == null) { - return const Center( - child: Text("Seleziona un brand per gestire i modelli"), - ); - } - - if (state.status == ProductStatus.loading && state.models.isEmpty) { - return const Center(child: CircularProgressIndicator()); - } - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Modelli di ${state.selectedBrand!.name}", - style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - ElevatedButton.icon( - onPressed: () => showModelDialog(context), - icon: const Icon(Icons.add), - label: const Text("NUOVO MODELLO"), - ), - ], - ), - const SizedBox(height: 16), - Expanded( - child: ListView.separated( - itemCount: state.models.length, - separatorBuilder: (_, _) => const Divider(height: 1), - itemBuilder: (context, index) { - final model = state.models[index]; - return ListTile( - title: Text(model.name), - subtitle: Text( - model.nameWithBrand, - ), // Quello gestito dal trigger! - trailing: Row( - mainAxisSize: MainAxisSize.min, - children: [ - IconButton( - icon: const Icon(Icons.edit_outlined), - onPressed: () => showModelDialog(context, model: model), - ), - IconButton( - icon: Icon( - model.isActive - ? Icons.visibility_outlined - : Icons.visibility_off_outlined, - color: model.isActive ? context.accent : Colors.grey, - ), - onPressed: () => context - .read() - .toggleStatus('model', model.id!, model.isActive), - ), - ], - ), - ); - }, - ), - ), - ], - ); - } -} diff --git a/lib/features/products/ui/product_dialogs.dart b/lib/features/products/ui/product_dialogs.dart deleted file mode 100644 index d7ac56f..0000000 --- a/lib/features/products/ui/product_dialogs.dart +++ /dev/null @@ -1,110 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flux/features/products/blocs/product_cubit.dart'; -import 'package:flux/features/products/models/brand_model.dart'; -import 'package:flux/features/products/models/model_model.dart'; - -void showBrandDialog(BuildContext context, {BrandModel? brand}) { - final controller = TextEditingController(text: brand?.name); - - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text(brand == null ? "Nuovo Brand" : "Modifica Brand"), - content: TextField( - controller: controller, - autofocus: true, - decoration: const InputDecoration( - labelText: "Nome Brand", - hintText: "es. Apple, Samsung...", - ), - onSubmitted: (_) => _submitBrand(controller, context, brand), - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text("Annulla"), - ), - ElevatedButton( - onPressed: () => _submitBrand(controller, context, brand), - child: const Text("Salva"), - ), - ], - ), - ); -} - -void _submitBrand( - TextEditingController controller, - BuildContext context, - BrandModel? brand, -) { - if (controller.text.trim().isNotEmpty) { - context.read().saveBrand(controller.text, id: brand?.id); - Navigator.pop(context); - } -} - -void showModelDialog(BuildContext context, {ModelModel? model}) { - final controller = TextEditingController(text: model?.name); - - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text(model == null ? "Nuovo Modello" : "Modifica Modello"), - content: TextField( - controller: controller, - autofocus: true, - decoration: const InputDecoration( - labelText: "Nome Modello", - hintText: "es. iPhone 15, Galaxy S24...", - ), - onSubmitted: (_) => _submitModel(controller, context, model), - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text("Annulla"), - ), - ElevatedButton( - onPressed: () => _submitModel(controller, context, model), - child: const Text("Salva"), - ), - ], - ), - ); -} - -void _submitModel( - TextEditingController controller, - BuildContext context, - ModelModel? model, -) { - if (controller.text.isNotEmpty) { - context.read().saveModel(controller.text, id: model?.id); - Navigator.pop(context); - } -} - -void confirmToggle(BuildContext context, String title, VoidCallback onConfirm) { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text("Sei sicuro?"), - content: Text("Stai per cambiare lo stato di: $title"), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text("Annulla"), - ), - TextButton( - onPressed: () { - onConfirm(); - Navigator.pop(context); - }, - child: const Text("Conferma", style: TextStyle(color: Colors.red)), - ), - ], - ), - ); -} diff --git a/lib/features/products/ui/products_screen.dart b/lib/features/products/ui/products_screen.dart deleted file mode 100644 index 03fa345..0000000 --- a/lib/features/products/ui/products_screen.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flux/core/theme/theme.dart'; -import 'package:flux/features/products/blocs/product_cubit.dart'; -import 'package:flux/features/products/ui/brand_selector.dart'; -import 'package:flux/features/products/ui/models_list.dart'; -import 'package:go_router/go_router.dart'; - -class ProductsScreen extends StatelessWidget { - const ProductsScreen({super.key}); - - @override - Widget build(BuildContext context) { - // Carichiamo i brand appena la pagina viene creata - context.read().loadBrands(); - - return Scaffold( - backgroundColor: context.background, - appBar: AppBar( - backgroundColor: context.background, - elevation: 0, - centerTitle: false, - leading: IconButton( - icon: const Icon(Icons.arrow_back), - onPressed: () => context.pop(), // Torna alla Dashboard - ), - title: Text( - "Anagrafica Prodotti", - style: TextStyle( - color: context.primaryText, - fontWeight: FontWeight.bold, - fontSize: 20, - ), - ), - ), - body: BlocConsumer( - listener: (context, state) { - if (state.status == ProductStatus.error) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(state.errorMessage ?? 'Errore')), - ); - } - }, - builder: (context, state) { - return Padding( - padding: const EdgeInsets.all(24.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Marche e Modelli", - style: TextStyle( - fontSize: 28, - fontWeight: FontWeight.bold, - color: context.accent, - ), - ), - const SizedBox(height: 24), - - // SEZIONE BRAND - BrandSelector(state), - - const SizedBox(height: 32), - - // SEZIONE MODELLI - Expanded(child: ModelsList(state)), - ], - ), - ); - }, - ), - ); - } -} diff --git a/lib/features/products/ui/round_action_button.dart b/lib/features/products/ui/round_action_button.dart deleted file mode 100644 index b174be0..0000000 --- a/lib/features/products/ui/round_action_button.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:flutter/material.dart'; - -class RoundActionButton extends StatelessWidget { - final IconData icon; - final VoidCallback onTap; - final String tooltip; - - const RoundActionButton({ - super.key, - required this.icon, - required this.onTap, - required this.tooltip, - }); - - @override - Widget build(BuildContext context) { - return IconButton.filledTonal( - onPressed: onTap, - icon: Icon(icon), - tooltip: tooltip, - ); - } -} diff --git a/lib/features/services/blocs/services_cubit.dart b/lib/features/services/blocs/services_cubit.dart index 83a3481..681b2ea 100644 --- a/lib/features/services/blocs/services_cubit.dart +++ b/lib/features/services/blocs/services_cubit.dart @@ -12,9 +12,9 @@ part 'services_state.dart'; class ServicesCubit extends Cubit { final ServicesRepository _repository = GetIt.I(); - final SessionBloc _sessionBloc; + final SessionBloc _sessionBloc = GetIt.I(); - ServicesCubit(this._sessionBloc) : super(const ServicesState()); + ServicesCubit() : super(const ServicesState()); // --- CARICAMENTO E PAGINAZIONE --- diff --git a/lib/features/services/ui/service_form_screen/finance_service_dialog.dart b/lib/features/services/ui/service_form_screen/finance_service_dialog.dart index 2efbfcd..a368942 100644 --- a/lib/features/services/ui/service_form_screen/finance_service_dialog.dart +++ b/lib/features/services/ui/service_form_screen/finance_service_dialog.dart @@ -1,10 +1,10 @@ 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/master_data/products/models/model_model.dart'; import 'package:flux/features/master_data/providers/blocs/provider_cubit.dart'; -import 'package:flux/features/products/blocs/product_cubit.dart'; import 'package:flux/features/services/models/fin_service_model.dart'; import 'package:flux/features/master_data/providers/models/provider_model.dart'; -import 'package:flux/features/products/models/model_model.dart'; // =========================================================================== // DIALOG PRINCIPALE @@ -12,11 +12,13 @@ import 'package:flux/features/products/models/model_model.dart'; class FinanceServiceDialog extends StatefulWidget { final List initialServices; final String currentStoreId; + final ProductCubit productCubit; const FinanceServiceDialog({ super.key, required this.initialServices, required this.currentStoreId, + required this.productCubit, }); @override @@ -40,60 +42,63 @@ class _FinanceServiceDialogState extends State { @override Widget build(BuildContext context) { - return AlertDialog( - title: Row( - children: [ - Icon( - Icons.payments_outlined, - color: Theme.of(context).colorScheme.primary, - ), - const SizedBox(width: 8), - Text(_isAddingNew ? "Dettagli Finanziamento" : "Finanziamenti"), - ], - ), - content: AnimatedSize( - duration: const Duration(milliseconds: 300), - child: SizedBox( - width: MediaQuery.of(context).size.width * 0.9, - child: _isAddingNew - ? _FinanceForm( - onSave: (newFin) => setState(() { - _tempList.add(newFin); - _isAddingNew = false; - }), - onCancel: () => setState(() => _isAddingNew = false), - ) - : BlocBuilder( - builder: (context, provState) { - return BlocBuilder( - builder: (context, prodState) { - return _FinanceList( - services: _tempList, - allProviders: - provState.allProviders, // Per vedere lo storico - allModels: prodState.models, - onDelete: (index) => - setState(() => _tempList.removeAt(index)), - onAddTap: () => setState(() => _isAddingNew = true), - ); - }, - ); - }, - ), + return BlocProvider.value( + value: widget.productCubit, + child: AlertDialog( + title: Row( + children: [ + Icon( + Icons.payments_outlined, + color: Theme.of(context).colorScheme.primary, + ), + const SizedBox(width: 8), + Text(_isAddingNew ? "Dettagli Finanziamento" : "Finanziamenti"), + ], ), + content: AnimatedSize( + duration: const Duration(milliseconds: 300), + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.9, + child: _isAddingNew + ? _FinanceForm( + onSave: (newFin) => setState(() { + _tempList.add(newFin); + _isAddingNew = false; + }), + onCancel: () => setState(() => _isAddingNew = false), + ) + : BlocBuilder( + builder: (context, provState) { + return BlocBuilder( + builder: (context, prodState) { + return _FinanceList( + services: _tempList, + allProviders: + provState.allProviders, // Per vedere lo storico + allModels: prodState.models, + onDelete: (index) => + setState(() => _tempList.removeAt(index)), + onAddTap: () => setState(() => _isAddingNew = true), + ); + }, + ); + }, + ), + ), + ), + actions: !_isAddingNew + ? [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text("Annulla"), + ), + ElevatedButton( + onPressed: () => Navigator.pop(context, _tempList), + child: const Text("Conferma"), + ), + ] + : null, ), - actions: !_isAddingNew - ? [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text("Annulla"), - ), - ElevatedButton( - onPressed: () => Navigator.pop(context, _tempList), - child: const Text("Conferma"), - ), - ] - : null, ); } } diff --git a/lib/features/services/ui/service_form_screen/services_grid.dart b/lib/features/services/ui/service_form_screen/services_grid.dart index fb441ee..66c06f1 100644 --- a/lib/features/services/ui/service_form_screen/services_grid.dart +++ b/lib/features/services/ui/service_form_screen/services_grid.dart @@ -1,10 +1,13 @@ 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/services/blocs/services_cubit.dart'; import 'package:flux/features/services/models/energy_service_model.dart'; +import 'package:flux/features/services/models/fin_service_model.dart'; import 'package:flux/features/services/models/service_model.dart'; import 'package:flux/features/services/ui/service_form_screen/action_card.dart'; import 'package:flux/features/services/ui/service_form_screen/energy_service_dialog.dart'; +import 'package:flux/features/services/ui/service_form_screen/finance_service_dialog.dart'; import 'package:flux/features/services/ui/service_form_screen/int_dialogs.dart'; // Assicurati di importare il modello class ServicesGrid extends StatelessWidget { @@ -142,8 +145,20 @@ class ServicesGrid extends StatelessWidget { count: service.finServices.length, icon: Icons.euro_symbol, color: Colors.teal, - onTap: () { - // TODO: Aprire la Dialog Finanziamenti complessa + onTap: () async { + final result = await showDialog>( + context: context, + builder: (context) => FinanceServiceDialog( + productCubit: context.read(), + currentStoreId: service.storeId, + initialServices: + service.finServices, // Passiamo la lista attuale + ), + ); + + if (result != null && context.mounted) { + context.read().updateFinServices(result); + } }, ), ActionCard( diff --git a/lib/main.dart b/lib/main.dart index 63891cd..0fc03ea 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -37,8 +37,16 @@ void main() async { BlocProvider( create: (context) => ThemeBloc()..add(LoadThemeEvent()), ), - BlocProvider( - create: (context) => SessionBloc()..add(AppStarted()), + BlocProvider(create: (_) => GetIt.I()), + BlocProvider(create: (_) => AuthBloc()), + BlocProvider(create: (_) => CompanyBloc()), + BlocProvider(create: (_) => StoreCubit()..loadStores()), + BlocProvider(create: (_) => CustomerCubit()), + BlocProvider(create: (_) => ProductCubit()), + BlocProvider(create: (_) => StaffCubit()..loadAllStaff()), + BlocProvider(create: (_) => ServicesCubit()), + BlocProvider( + create: (_) => ProvidersCubit()..loadProviders(null), ), ], child: const FluxApp(), @@ -65,6 +73,7 @@ Future setupLocator() async { getIt.registerLazySingleton(() => StaffRepository()); getIt.registerLazySingleton(() => ServicesRepository()); getIt.registerLazySingleton(() => ProviderRepository()); + getIt.registerSingleton(SessionBloc()..add(AppStarted())); } class FluxApp extends StatefulWidget { @@ -86,41 +95,17 @@ class _FluxAppState extends State { @override Widget build(BuildContext context) { - return MultiBlocProvider( - providers: [ - BlocProvider(create: (_) => AuthBloc()), - BlocProvider(create: (_) => CompanyBloc()), - BlocProvider( - create: (_) => StoreCubit(context.read())..loadStores(), - ), - BlocProvider(create: (_) => CustomerCubit()), - BlocProvider( - create: (context) => ProductCubit(context.read()), - ), - BlocProvider( - create: (_) => - StaffCubit(context.read())..loadAllStaff(), - ), - BlocProvider( - create: (_) => ServicesCubit(context.read()), - ), - BlocProvider( - create: (_) => - ProvidersCubit(context.read())..loadProviders(null), - ), - ], - child: BlocBuilder( - builder: (context, state) { - return MaterialApp.router( - title: 'FLUX Gestionale', - debugShowCheckedModeBanner: false, - theme: fluxLightTheme, - darkTheme: fluxDarkTheme, - themeMode: state.currentTheme.themeMode, - routerConfig: _router, // Usa l'istanza mantenuta nello stato - ); - }, - ), + return BlocBuilder( + builder: (context, state) { + return MaterialApp.router( + title: 'FLUX Gestionale', + debugShowCheckedModeBanner: false, + theme: fluxLightTheme, + darkTheme: fluxDarkTheme, + themeMode: state.currentTheme.themeMode, + routerConfig: _router, // Usa l'istanza mantenuta nello stato + ); + }, ); } }